BUG 9766: Cache name_to_sid/sid_to_name correctly.
[Samba.git] / source3 / smbd / reply.c
blob31f4e2fc456046dcd643730863333d2eb5e93382
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 "rpc_client/cli_spoolss.h"
36 #include "rpc_client/init_spoolss.h"
37 #include "rpc_server/rpc_ncacn_np.h"
38 #include "libcli/security/security.h"
39 #include "libsmb/nmblib.h"
40 #include "auth.h"
41 #include "smbprofile.h"
43 /****************************************************************************
44 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
45 path or anything including wildcards.
46 We're assuming here that '/' is not the second byte in any multibyte char
47 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
48 set.
49 ****************************************************************************/
51 /* Custom version for processing POSIX paths. */
52 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
54 static NTSTATUS check_path_syntax_internal(char *path,
55 bool posix_path,
56 bool *p_last_component_contains_wcard)
58 char *d = path;
59 const char *s = path;
60 NTSTATUS ret = NT_STATUS_OK;
61 bool start_of_name_component = True;
62 bool stream_started = false;
64 *p_last_component_contains_wcard = False;
66 while (*s) {
67 if (stream_started) {
68 switch (*s) {
69 case '/':
70 case '\\':
71 return NT_STATUS_OBJECT_NAME_INVALID;
72 case ':':
73 if (s[1] == '\0') {
74 return NT_STATUS_OBJECT_NAME_INVALID;
76 if (strchr_m(&s[1], ':')) {
77 return NT_STATUS_OBJECT_NAME_INVALID;
79 break;
83 if ((*s == ':') && !posix_path && !stream_started) {
84 if (*p_last_component_contains_wcard) {
85 return NT_STATUS_OBJECT_NAME_INVALID;
87 /* Stream names allow more characters than file names.
88 We're overloading posix_path here to allow a wider
89 range of characters. If stream_started is true this
90 is still a Windows path even if posix_path is true.
91 JRA.
93 stream_started = true;
94 start_of_name_component = false;
95 posix_path = true;
97 if (s[1] == '\0') {
98 return NT_STATUS_OBJECT_NAME_INVALID;
102 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
104 * Safe to assume is not the second part of a mb char
105 * as this is handled below.
107 /* Eat multiple '/' or '\\' */
108 while (IS_PATH_SEP(*s,posix_path)) {
109 s++;
111 if ((d != path) && (*s != '\0')) {
112 /* We only care about non-leading or trailing '/' or '\\' */
113 *d++ = '/';
116 start_of_name_component = True;
117 /* New component. */
118 *p_last_component_contains_wcard = False;
119 continue;
122 if (start_of_name_component) {
123 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
124 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
127 * No mb char starts with '.' so we're safe checking the directory separator here.
130 /* If we just added a '/' - delete it */
131 if ((d > path) && (*(d-1) == '/')) {
132 *(d-1) = '\0';
133 d--;
136 /* Are we at the start ? Can't go back further if so. */
137 if (d <= path) {
138 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
139 break;
141 /* Go back one level... */
142 /* We know this is safe as '/' cannot be part of a mb sequence. */
143 /* NOTE - if this assumption is invalid we are not in good shape... */
144 /* Decrement d first as d points to the *next* char to write into. */
145 for (d--; d > path; d--) {
146 if (*d == '/')
147 break;
149 s += 2; /* Else go past the .. */
150 /* We're still at the start of a name component, just the previous one. */
151 continue;
153 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
154 if (posix_path) {
155 /* Eat the '.' */
156 s++;
157 continue;
163 if (!(*s & 0x80)) {
164 if (!posix_path) {
165 if (*s <= 0x1f || *s == '|') {
166 return NT_STATUS_OBJECT_NAME_INVALID;
168 switch (*s) {
169 case '*':
170 case '?':
171 case '<':
172 case '>':
173 case '"':
174 *p_last_component_contains_wcard = True;
175 break;
176 default:
177 break;
180 *d++ = *s++;
181 } else {
182 size_t siz;
183 /* Get the size of the next MB character. */
184 next_codepoint(s,&siz);
185 switch(siz) {
186 case 5:
187 *d++ = *s++;
188 /*fall through*/
189 case 4:
190 *d++ = *s++;
191 /*fall through*/
192 case 3:
193 *d++ = *s++;
194 /*fall through*/
195 case 2:
196 *d++ = *s++;
197 /*fall through*/
198 case 1:
199 *d++ = *s++;
200 break;
201 default:
202 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
203 *d = '\0';
204 return NT_STATUS_INVALID_PARAMETER;
207 start_of_name_component = False;
210 *d = '\0';
212 return ret;
215 /****************************************************************************
216 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
217 No wildcards allowed.
218 ****************************************************************************/
220 NTSTATUS check_path_syntax(char *path)
222 bool ignore;
223 return check_path_syntax_internal(path, False, &ignore);
226 /****************************************************************************
227 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
228 Wildcards allowed - p_contains_wcard returns true if the last component contained
229 a wildcard.
230 ****************************************************************************/
232 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
234 return check_path_syntax_internal(path, False, p_contains_wcard);
237 /****************************************************************************
238 Check the path for a POSIX client.
239 We're assuming here that '/' is not the second byte in any multibyte char
240 set (a safe assumption).
241 ****************************************************************************/
243 NTSTATUS check_path_syntax_posix(char *path)
245 bool ignore;
246 return check_path_syntax_internal(path, True, &ignore);
249 /****************************************************************************
250 Pull a string and check the path allowing a wilcard - provide for error return.
251 ****************************************************************************/
253 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
254 const char *base_ptr,
255 uint16 smb_flags2,
256 char **pp_dest,
257 const char *src,
258 size_t src_len,
259 int flags,
260 NTSTATUS *err,
261 bool *contains_wcard)
263 size_t ret;
265 *pp_dest = NULL;
267 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
268 src_len, flags);
270 if (!*pp_dest) {
271 *err = NT_STATUS_INVALID_PARAMETER;
272 return ret;
275 *contains_wcard = False;
277 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
279 * For a DFS path the function parse_dfs_path()
280 * will do the path processing, just make a copy.
282 *err = NT_STATUS_OK;
283 return ret;
286 if (lp_posix_pathnames()) {
287 *err = check_path_syntax_posix(*pp_dest);
288 } else {
289 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
292 return ret;
295 /****************************************************************************
296 Pull a string and check the path - provide for error return.
297 ****************************************************************************/
299 size_t srvstr_get_path(TALLOC_CTX *ctx,
300 const char *base_ptr,
301 uint16 smb_flags2,
302 char **pp_dest,
303 const char *src,
304 size_t src_len,
305 int flags,
306 NTSTATUS *err)
308 bool ignore;
309 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
310 src_len, flags, err, &ignore);
313 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
314 char **pp_dest, const char *src, int flags,
315 NTSTATUS *err, bool *contains_wcard)
317 return srvstr_get_path_wcard(mem_ctx, (char *)req->inbuf, req->flags2,
318 pp_dest, src, smbreq_bufrem(req, src),
319 flags, err, contains_wcard);
322 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
323 char **pp_dest, const char *src, int flags,
324 NTSTATUS *err)
326 bool ignore;
327 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
328 flags, err, &ignore);
331 /****************************************************************************
332 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
333 ****************************************************************************/
335 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
336 files_struct *fsp)
338 if ((fsp == NULL) || (conn == NULL)) {
339 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
340 return False;
342 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
343 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
344 return False;
346 return True;
349 /****************************************************************************
350 Check if we have a correct fsp pointing to a file.
351 ****************************************************************************/
353 bool check_fsp(connection_struct *conn, struct smb_request *req,
354 files_struct *fsp)
356 if (!check_fsp_open(conn, req, fsp)) {
357 return False;
359 if (fsp->is_directory) {
360 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
361 return False;
363 if (fsp->fh->fd == -1) {
364 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
365 return False;
367 fsp->num_smb_operations++;
368 return True;
371 /****************************************************************************
372 Check if we have a correct fsp pointing to a quota fake file. Replacement for
373 the CHECK_NTQUOTA_HANDLE_OK macro.
374 ****************************************************************************/
376 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
377 files_struct *fsp)
379 if (!check_fsp_open(conn, req, fsp)) {
380 return false;
383 if (fsp->is_directory) {
384 return false;
387 if (fsp->fake_file_handle == NULL) {
388 return false;
391 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
392 return false;
395 if (fsp->fake_file_handle->private_data == NULL) {
396 return false;
399 return true;
402 static bool netbios_session_retarget(struct smbd_server_connection *sconn,
403 const char *name, int name_type)
405 char *trim_name;
406 char *trim_name_type;
407 const char *retarget_parm;
408 char *retarget;
409 char *p;
410 int retarget_type = 0x20;
411 int retarget_port = 139;
412 struct sockaddr_storage retarget_addr;
413 struct sockaddr_in *in_addr;
414 bool ret = false;
415 uint8_t outbuf[10];
417 if (get_socket_port(sconn->sock) != 139) {
418 return false;
421 trim_name = talloc_strdup(talloc_tos(), name);
422 if (trim_name == NULL) {
423 goto fail;
425 trim_char(trim_name, ' ', ' ');
427 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
428 name_type);
429 if (trim_name_type == NULL) {
430 goto fail;
433 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
434 trim_name_type, NULL);
435 if (retarget_parm == NULL) {
436 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
437 trim_name, NULL);
439 if (retarget_parm == NULL) {
440 goto fail;
443 retarget = talloc_strdup(trim_name, retarget_parm);
444 if (retarget == NULL) {
445 goto fail;
448 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
450 p = strchr(retarget, ':');
451 if (p != NULL) {
452 *p++ = '\0';
453 retarget_port = atoi(p);
456 p = strchr_m(retarget, '#');
457 if (p != NULL) {
458 *p++ = '\0';
459 if (sscanf(p, "%x", &retarget_type) != 1) {
460 goto fail;
464 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
465 if (!ret) {
466 DEBUG(10, ("could not resolve %s\n", retarget));
467 goto fail;
470 if (retarget_addr.ss_family != AF_INET) {
471 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
472 goto fail;
475 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
477 _smb_setlen(outbuf, 6);
478 SCVAL(outbuf, 0, 0x84);
479 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
480 *(uint16_t *)(outbuf+8) = htons(retarget_port);
482 if (!srv_send_smb(sconn, (char *)outbuf, false, 0, false,
483 NULL)) {
484 exit_server_cleanly("netbios_session_regarget: srv_send_smb "
485 "failed.");
488 ret = true;
489 fail:
490 TALLOC_FREE(trim_name);
491 return ret;
494 /****************************************************************************
495 Reply to a (netbios-level) special message.
496 ****************************************************************************/
498 void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inbuf_size)
500 int msg_type = CVAL(inbuf,0);
501 int msg_flags = CVAL(inbuf,1);
503 * We only really use 4 bytes of the outbuf, but for the smb_setlen
504 * calculation & friends (srv_send_smb uses that) we need the full smb
505 * header.
507 char outbuf[smb_size];
509 memset(outbuf, '\0', sizeof(outbuf));
511 smb_setlen(outbuf,0);
513 switch (msg_type) {
514 case 0x81: /* session request */
516 /* inbuf_size is guarenteed to be at least 4. */
517 fstring name1,name2;
518 int name_type1, name_type2;
519 int name_len1, name_len2;
521 *name1 = *name2 = 0;
523 if (sconn->nbt.got_session) {
524 exit_server_cleanly("multiple session request not permitted");
527 SCVAL(outbuf,0,0x82);
528 SCVAL(outbuf,3,0);
530 /* inbuf_size is guaranteed to be at least 4. */
531 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
532 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
533 DEBUG(0,("Invalid name length in session request\n"));
534 break;
536 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
537 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
538 DEBUG(0,("Invalid name length in session request\n"));
539 break;
542 name_type1 = name_extract((unsigned char *)inbuf,
543 inbuf_size,(unsigned int)4,name1);
544 name_type2 = name_extract((unsigned char *)inbuf,
545 inbuf_size,(unsigned int)(4 + name_len1),name2);
547 if (name_type1 == -1 || name_type2 == -1) {
548 DEBUG(0,("Invalid name type in session request\n"));
549 break;
552 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
553 name1, name_type1, name2, name_type2));
555 if (netbios_session_retarget(sconn, name1, name_type1)) {
556 exit_server_cleanly("retargeted client");
560 * Windows NT/2k uses "*SMBSERVER" and XP uses
561 * "*SMBSERV" arrggg!!!
563 if (strequal(name1, "*SMBSERVER ")
564 || strequal(name1, "*SMBSERV ")) {
565 fstrcpy(name1, sconn->client_id.addr);
568 set_local_machine_name(name1, True);
569 set_remote_machine_name(name2, True);
571 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
572 get_local_machine_name(), get_remote_machine_name(),
573 name_type2));
575 if (name_type2 == 'R') {
576 /* We are being asked for a pathworks session ---
577 no thanks! */
578 SCVAL(outbuf, 0,0x83);
579 break;
582 /* only add the client's machine name to the list
583 of possibly valid usernames if we are operating
584 in share mode security */
585 if (lp_security() == SEC_SHARE) {
586 add_session_user(sconn, get_remote_machine_name());
589 reload_services(sconn->msg_ctx, sconn->sock, True);
590 reopen_logs();
592 sconn->nbt.got_session = true;
593 break;
596 case 0x89: /* session keepalive request
597 (some old clients produce this?) */
598 SCVAL(outbuf,0,SMBkeepalive);
599 SCVAL(outbuf,3,0);
600 break;
602 case 0x82: /* positive session response */
603 case 0x83: /* negative session response */
604 case 0x84: /* retarget session response */
605 DEBUG(0,("Unexpected session response\n"));
606 break;
608 case SMBkeepalive: /* session keepalive */
609 default:
610 return;
613 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
614 msg_type, msg_flags));
616 srv_send_smb(sconn, outbuf, false, 0, false, NULL);
617 return;
620 /****************************************************************************
621 Reply to a tcon.
622 conn POINTER CAN BE NULL HERE !
623 ****************************************************************************/
625 void reply_tcon(struct smb_request *req)
627 connection_struct *conn = req->conn;
628 const char *service;
629 char *service_buf = NULL;
630 char *password = NULL;
631 char *dev = NULL;
632 int pwlen=0;
633 NTSTATUS nt_status;
634 const char *p;
635 DATA_BLOB password_blob;
636 TALLOC_CTX *ctx = talloc_tos();
637 struct smbd_server_connection *sconn = req->sconn;
639 START_PROFILE(SMBtcon);
641 if (req->buflen < 4) {
642 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
643 END_PROFILE(SMBtcon);
644 return;
647 p = (const char *)req->buf + 1;
648 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
649 p += 1;
650 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
651 p += pwlen+1;
652 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
653 p += 1;
655 if (service_buf == NULL || password == NULL || dev == NULL) {
656 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
657 END_PROFILE(SMBtcon);
658 return;
660 p = strrchr_m(service_buf,'\\');
661 if (p) {
662 service = p+1;
663 } else {
664 service = service_buf;
667 password_blob = data_blob(password, pwlen+1);
669 conn = make_connection(sconn,service,password_blob,dev,
670 req->vuid,&nt_status);
671 req->conn = conn;
673 data_blob_clear_free(&password_blob);
675 if (!conn) {
676 reply_nterror(req, nt_status);
677 END_PROFILE(SMBtcon);
678 return;
681 reply_outbuf(req, 2, 0);
682 SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
683 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
684 SSVAL(req->outbuf,smb_tid,conn->cnum);
686 DEBUG(3,("tcon service=%s cnum=%d\n",
687 service, conn->cnum));
689 END_PROFILE(SMBtcon);
690 return;
693 /****************************************************************************
694 Reply to a tcon and X.
695 conn POINTER CAN BE NULL HERE !
696 ****************************************************************************/
698 void reply_tcon_and_X(struct smb_request *req)
700 connection_struct *conn = req->conn;
701 const char *service = NULL;
702 DATA_BLOB password;
703 TALLOC_CTX *ctx = talloc_tos();
704 /* what the cleint thinks the device is */
705 char *client_devicetype = NULL;
706 /* what the server tells the client the share represents */
707 const char *server_devicetype;
708 NTSTATUS nt_status;
709 int passlen;
710 char *path = NULL;
711 const char *p, *q;
712 uint16 tcon_flags;
713 struct smbd_server_connection *sconn = req->sconn;
715 START_PROFILE(SMBtconX);
717 if (req->wct < 4) {
718 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
719 END_PROFILE(SMBtconX);
720 return;
723 passlen = SVAL(req->vwv+3, 0);
724 tcon_flags = SVAL(req->vwv+2, 0);
726 /* we might have to close an old one */
727 if ((tcon_flags & 0x1) && conn) {
728 close_cnum(conn,req->vuid);
729 req->conn = NULL;
730 conn = NULL;
733 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
734 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
735 END_PROFILE(SMBtconX);
736 return;
739 if (sconn->smb1.negprot.encrypted_passwords) {
740 password = data_blob_talloc(talloc_tos(), req->buf, passlen);
741 if (lp_security() == SEC_SHARE) {
743 * Security = share always has a pad byte
744 * after the password.
746 p = (const char *)req->buf + passlen + 1;
747 } else {
748 p = (const char *)req->buf + passlen;
750 } else {
751 password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
752 /* Ensure correct termination */
753 password.data[passlen]=0;
754 p = (const char *)req->buf + passlen + 1;
757 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
759 if (path == NULL) {
760 data_blob_clear_free(&password);
761 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
762 END_PROFILE(SMBtconX);
763 return;
767 * the service name can be either: \\server\share
768 * or share directly like on the DELL PowerVault 705
770 if (*path=='\\') {
771 q = strchr_m(path+2,'\\');
772 if (!q) {
773 data_blob_clear_free(&password);
774 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
775 END_PROFILE(SMBtconX);
776 return;
778 service = q+1;
779 } else {
780 service = path;
783 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
784 &client_devicetype, p,
785 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
787 if (client_devicetype == NULL) {
788 data_blob_clear_free(&password);
789 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
790 END_PROFILE(SMBtconX);
791 return;
794 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
796 conn = make_connection(sconn, service, password, client_devicetype,
797 req->vuid, &nt_status);
798 req->conn =conn;
800 data_blob_clear_free(&password);
802 if (!conn) {
803 reply_nterror(req, nt_status);
804 END_PROFILE(SMBtconX);
805 return;
808 if ( IS_IPC(conn) )
809 server_devicetype = "IPC";
810 else if ( IS_PRINT(conn) )
811 server_devicetype = "LPT1:";
812 else
813 server_devicetype = "A:";
815 if (get_Protocol() < PROTOCOL_NT1) {
816 reply_outbuf(req, 2, 0);
817 if (message_push_string(&req->outbuf, server_devicetype,
818 STR_TERMINATE|STR_ASCII) == -1) {
819 reply_nterror(req, NT_STATUS_NO_MEMORY);
820 END_PROFILE(SMBtconX);
821 return;
823 } else {
824 /* NT sets the fstype of IPC$ to the null string */
825 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
827 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
828 /* Return permissions. */
829 uint32 perm1 = 0;
830 uint32 perm2 = 0;
832 reply_outbuf(req, 7, 0);
834 if (IS_IPC(conn)) {
835 perm1 = FILE_ALL_ACCESS;
836 perm2 = FILE_ALL_ACCESS;
837 } else {
838 perm1 = conn->share_access;
841 SIVAL(req->outbuf, smb_vwv3, perm1);
842 SIVAL(req->outbuf, smb_vwv5, perm2);
843 } else {
844 reply_outbuf(req, 3, 0);
847 if ((message_push_string(&req->outbuf, server_devicetype,
848 STR_TERMINATE|STR_ASCII) == -1)
849 || (message_push_string(&req->outbuf, fstype,
850 STR_TERMINATE) == -1)) {
851 reply_nterror(req, NT_STATUS_NO_MEMORY);
852 END_PROFILE(SMBtconX);
853 return;
856 /* what does setting this bit do? It is set by NT4 and
857 may affect the ability to autorun mounted cdroms */
858 SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
859 (lp_csc_policy(SNUM(conn)) << 2));
861 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
862 DEBUG(2,("Serving %s as a Dfs root\n",
863 lp_servicename(SNUM(conn)) ));
864 SSVAL(req->outbuf, smb_vwv2,
865 SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
870 DEBUG(3,("tconX service=%s \n",
871 service));
873 /* set the incoming and outgoing tid to the just created one */
874 SSVAL(req->inbuf,smb_tid,conn->cnum);
875 SSVAL(req->outbuf,smb_tid,conn->cnum);
877 END_PROFILE(SMBtconX);
879 req->tid = conn->cnum;
880 chain_reply(req);
881 return;
884 /****************************************************************************
885 Reply to an unknown type.
886 ****************************************************************************/
888 void reply_unknown_new(struct smb_request *req, uint8 type)
890 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
891 smb_fn_name(type), type, type));
892 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
893 return;
896 /****************************************************************************
897 Reply to an ioctl.
898 conn POINTER CAN BE NULL HERE !
899 ****************************************************************************/
901 void reply_ioctl(struct smb_request *req)
903 connection_struct *conn = req->conn;
904 uint16 device;
905 uint16 function;
906 uint32 ioctl_code;
907 int replysize;
908 char *p;
910 START_PROFILE(SMBioctl);
912 if (req->wct < 3) {
913 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
914 END_PROFILE(SMBioctl);
915 return;
918 device = SVAL(req->vwv+1, 0);
919 function = SVAL(req->vwv+2, 0);
920 ioctl_code = (device << 16) + function;
922 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
924 switch (ioctl_code) {
925 case IOCTL_QUERY_JOB_INFO:
926 replysize = 32;
927 break;
928 default:
929 reply_force_doserror(req, ERRSRV, ERRnosupport);
930 END_PROFILE(SMBioctl);
931 return;
934 reply_outbuf(req, 8, replysize+1);
935 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
936 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
937 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
938 p = smb_buf(req->outbuf);
939 memset(p, '\0', replysize+1); /* valgrind-safe. */
940 p += 1; /* Allow for alignment */
942 switch (ioctl_code) {
943 case IOCTL_QUERY_JOB_INFO:
945 files_struct *fsp = file_fsp(
946 req, SVAL(req->vwv+0, 0));
947 if (!fsp) {
948 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
949 END_PROFILE(SMBioctl);
950 return;
952 /* Job number */
953 if (fsp->print_file) {
954 SSVAL(p, 0, fsp->print_file->rap_jobid);
955 } else {
956 SSVAL(p, 0, 0);
958 srvstr_push((char *)req->outbuf, req->flags2, p+2,
959 global_myname(), 15,
960 STR_TERMINATE|STR_ASCII);
961 if (conn) {
962 srvstr_push((char *)req->outbuf, req->flags2,
963 p+18, lp_servicename(SNUM(conn)),
964 13, STR_TERMINATE|STR_ASCII);
965 } else {
966 memset(p+18, 0, 13);
968 break;
972 END_PROFILE(SMBioctl);
973 return;
976 /****************************************************************************
977 Strange checkpath NTSTATUS mapping.
978 ****************************************************************************/
980 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
982 /* Strange DOS error code semantics only for checkpath... */
983 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
984 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
985 /* We need to map to ERRbadpath */
986 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
989 return status;
992 /****************************************************************************
993 Reply to a checkpath.
994 ****************************************************************************/
996 void reply_checkpath(struct smb_request *req)
998 connection_struct *conn = req->conn;
999 struct smb_filename *smb_fname = NULL;
1000 char *name = NULL;
1001 NTSTATUS status;
1002 TALLOC_CTX *ctx = talloc_tos();
1004 START_PROFILE(SMBcheckpath);
1006 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1007 STR_TERMINATE, &status);
1009 if (!NT_STATUS_IS_OK(status)) {
1010 status = map_checkpath_error(req->flags2, status);
1011 reply_nterror(req, status);
1012 END_PROFILE(SMBcheckpath);
1013 return;
1016 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1018 status = filename_convert(ctx,
1019 conn,
1020 req->flags2 & FLAGS2_DFS_PATHNAMES,
1021 name,
1023 NULL,
1024 &smb_fname);
1026 if (!NT_STATUS_IS_OK(status)) {
1027 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1028 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1029 ERRSRV, ERRbadpath);
1030 END_PROFILE(SMBcheckpath);
1031 return;
1033 goto path_err;
1036 if (!VALID_STAT(smb_fname->st) &&
1037 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1038 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1039 smb_fname_str_dbg(smb_fname), strerror(errno)));
1040 status = map_nt_error_from_unix(errno);
1041 goto path_err;
1044 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1045 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1046 ERRDOS, ERRbadpath);
1047 goto out;
1050 reply_outbuf(req, 0, 0);
1052 path_err:
1053 /* We special case this - as when a Windows machine
1054 is parsing a path is steps through the components
1055 one at a time - if a component fails it expects
1056 ERRbadpath, not ERRbadfile.
1058 status = map_checkpath_error(req->flags2, status);
1059 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1061 * Windows returns different error codes if
1062 * the parent directory is valid but not the
1063 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1064 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1065 * if the path is invalid.
1067 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1068 ERRDOS, ERRbadpath);
1069 goto out;
1072 reply_nterror(req, status);
1074 out:
1075 TALLOC_FREE(smb_fname);
1076 END_PROFILE(SMBcheckpath);
1077 return;
1080 /****************************************************************************
1081 Reply to a getatr.
1082 ****************************************************************************/
1084 void reply_getatr(struct smb_request *req)
1086 connection_struct *conn = req->conn;
1087 struct smb_filename *smb_fname = NULL;
1088 char *fname = NULL;
1089 int mode=0;
1090 SMB_OFF_T size=0;
1091 time_t mtime=0;
1092 const char *p;
1093 NTSTATUS status;
1094 TALLOC_CTX *ctx = talloc_tos();
1095 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1097 START_PROFILE(SMBgetatr);
1099 p = (const char *)req->buf + 1;
1100 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1101 if (!NT_STATUS_IS_OK(status)) {
1102 reply_nterror(req, status);
1103 goto out;
1106 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1107 under WfWg - weird! */
1108 if (*fname == '\0') {
1109 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1110 if (!CAN_WRITE(conn)) {
1111 mode |= FILE_ATTRIBUTE_READONLY;
1113 size = 0;
1114 mtime = 0;
1115 } else {
1116 status = filename_convert(ctx,
1117 conn,
1118 req->flags2 & FLAGS2_DFS_PATHNAMES,
1119 fname,
1121 NULL,
1122 &smb_fname);
1123 if (!NT_STATUS_IS_OK(status)) {
1124 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1125 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1126 ERRSRV, ERRbadpath);
1127 goto out;
1129 reply_nterror(req, status);
1130 goto out;
1132 if (!VALID_STAT(smb_fname->st) &&
1133 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1134 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1135 smb_fname_str_dbg(smb_fname),
1136 strerror(errno)));
1137 reply_nterror(req, map_nt_error_from_unix(errno));
1138 goto out;
1141 mode = dos_mode(conn, smb_fname);
1142 size = smb_fname->st.st_ex_size;
1144 if (ask_sharemode) {
1145 struct timespec write_time_ts;
1146 struct file_id fileid;
1148 ZERO_STRUCT(write_time_ts);
1149 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1150 get_file_infos(fileid, 0, NULL, &write_time_ts);
1151 if (!null_timespec(write_time_ts)) {
1152 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1156 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1157 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1158 size = 0;
1162 reply_outbuf(req, 10, 0);
1164 SSVAL(req->outbuf,smb_vwv0,mode);
1165 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1166 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1167 } else {
1168 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1170 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1172 if (get_Protocol() >= PROTOCOL_NT1) {
1173 SSVAL(req->outbuf, smb_flg2,
1174 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1177 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1178 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1180 out:
1181 TALLOC_FREE(smb_fname);
1182 TALLOC_FREE(fname);
1183 END_PROFILE(SMBgetatr);
1184 return;
1187 /****************************************************************************
1188 Reply to a setatr.
1189 ****************************************************************************/
1191 void reply_setatr(struct smb_request *req)
1193 struct smb_file_time ft;
1194 connection_struct *conn = req->conn;
1195 struct smb_filename *smb_fname = NULL;
1196 char *fname = NULL;
1197 int mode;
1198 time_t mtime;
1199 const char *p;
1200 NTSTATUS status;
1201 TALLOC_CTX *ctx = talloc_tos();
1203 START_PROFILE(SMBsetatr);
1205 ZERO_STRUCT(ft);
1207 if (req->wct < 2) {
1208 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1209 goto out;
1212 p = (const char *)req->buf + 1;
1213 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1214 if (!NT_STATUS_IS_OK(status)) {
1215 reply_nterror(req, status);
1216 goto out;
1219 status = filename_convert(ctx,
1220 conn,
1221 req->flags2 & FLAGS2_DFS_PATHNAMES,
1222 fname,
1224 NULL,
1225 &smb_fname);
1226 if (!NT_STATUS_IS_OK(status)) {
1227 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1228 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1229 ERRSRV, ERRbadpath);
1230 goto out;
1232 reply_nterror(req, status);
1233 goto out;
1236 if (smb_fname->base_name[0] == '.' &&
1237 smb_fname->base_name[1] == '\0') {
1239 * Not sure here is the right place to catch this
1240 * condition. Might be moved to somewhere else later -- vl
1242 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1243 goto out;
1246 mode = SVAL(req->vwv+0, 0);
1247 mtime = srv_make_unix_date3(req->vwv+1);
1249 ft.mtime = convert_time_t_to_timespec(mtime);
1250 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1251 if (!NT_STATUS_IS_OK(status)) {
1252 reply_nterror(req, status);
1253 goto out;
1256 if (mode != FILE_ATTRIBUTE_NORMAL) {
1257 if (VALID_STAT_OF_DIR(smb_fname->st))
1258 mode |= FILE_ATTRIBUTE_DIRECTORY;
1259 else
1260 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1262 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1263 false) != 0) {
1264 reply_nterror(req, map_nt_error_from_unix(errno));
1265 goto out;
1269 reply_outbuf(req, 0, 0);
1271 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1272 mode));
1273 out:
1274 TALLOC_FREE(smb_fname);
1275 END_PROFILE(SMBsetatr);
1276 return;
1279 /****************************************************************************
1280 Reply to a dskattr.
1281 ****************************************************************************/
1283 void reply_dskattr(struct smb_request *req)
1285 connection_struct *conn = req->conn;
1286 uint64_t dfree,dsize,bsize;
1287 START_PROFILE(SMBdskattr);
1289 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1290 reply_nterror(req, map_nt_error_from_unix(errno));
1291 END_PROFILE(SMBdskattr);
1292 return;
1295 reply_outbuf(req, 5, 0);
1297 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1298 double total_space, free_space;
1299 /* we need to scale this to a number that DOS6 can handle. We
1300 use floating point so we can handle large drives on systems
1301 that don't have 64 bit integers
1303 we end up displaying a maximum of 2G to DOS systems
1305 total_space = dsize * (double)bsize;
1306 free_space = dfree * (double)bsize;
1308 dsize = (uint64_t)((total_space+63*512) / (64*512));
1309 dfree = (uint64_t)((free_space+63*512) / (64*512));
1311 if (dsize > 0xFFFF) dsize = 0xFFFF;
1312 if (dfree > 0xFFFF) dfree = 0xFFFF;
1314 SSVAL(req->outbuf,smb_vwv0,dsize);
1315 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1316 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1317 SSVAL(req->outbuf,smb_vwv3,dfree);
1318 } else {
1319 SSVAL(req->outbuf,smb_vwv0,dsize);
1320 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1321 SSVAL(req->outbuf,smb_vwv2,512);
1322 SSVAL(req->outbuf,smb_vwv3,dfree);
1325 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1327 END_PROFILE(SMBdskattr);
1328 return;
1332 * Utility function to split the filename from the directory.
1334 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1335 char **fname_dir_out,
1336 char **fname_mask_out)
1338 const char *p = NULL;
1339 char *fname_dir = NULL;
1340 char *fname_mask = NULL;
1342 p = strrchr_m(fname_in, '/');
1343 if (!p) {
1344 fname_dir = talloc_strdup(ctx, ".");
1345 fname_mask = talloc_strdup(ctx, fname_in);
1346 } else {
1347 fname_dir = talloc_strndup(ctx, fname_in,
1348 PTR_DIFF(p, fname_in));
1349 fname_mask = talloc_strdup(ctx, p+1);
1352 if (!fname_dir || !fname_mask) {
1353 TALLOC_FREE(fname_dir);
1354 TALLOC_FREE(fname_mask);
1355 return NT_STATUS_NO_MEMORY;
1358 *fname_dir_out = fname_dir;
1359 *fname_mask_out = fname_mask;
1360 return NT_STATUS_OK;
1363 /****************************************************************************
1364 Reply to a search.
1365 Can be called from SMBsearch, SMBffirst or SMBfunique.
1366 ****************************************************************************/
1368 void reply_search(struct smb_request *req)
1370 connection_struct *conn = req->conn;
1371 char *path = NULL;
1372 const char *mask = NULL;
1373 char *directory = NULL;
1374 struct smb_filename *smb_fname = NULL;
1375 char *fname = NULL;
1376 SMB_OFF_T size;
1377 uint32 mode;
1378 struct timespec date;
1379 uint32 dirtype;
1380 unsigned int numentries = 0;
1381 unsigned int maxentries = 0;
1382 bool finished = False;
1383 const char *p;
1384 int status_len;
1385 char status[21];
1386 int dptr_num= -1;
1387 bool check_descend = False;
1388 bool expect_close = False;
1389 NTSTATUS nt_status;
1390 bool mask_contains_wcard = False;
1391 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1392 TALLOC_CTX *ctx = talloc_tos();
1393 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1394 struct dptr_struct *dirptr = NULL;
1395 struct smbd_server_connection *sconn = req->sconn;
1397 START_PROFILE(SMBsearch);
1399 if (req->wct < 2) {
1400 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1401 goto out;
1404 if (lp_posix_pathnames()) {
1405 reply_unknown_new(req, req->cmd);
1406 goto out;
1409 /* If we were called as SMBffirst then we must expect close. */
1410 if(req->cmd == SMBffirst) {
1411 expect_close = True;
1414 reply_outbuf(req, 1, 3);
1415 maxentries = SVAL(req->vwv+0, 0);
1416 dirtype = SVAL(req->vwv+1, 0);
1417 p = (const char *)req->buf + 1;
1418 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1419 &nt_status, &mask_contains_wcard);
1420 if (!NT_STATUS_IS_OK(nt_status)) {
1421 reply_nterror(req, nt_status);
1422 goto out;
1425 p++;
1426 status_len = SVAL(p, 0);
1427 p += 2;
1429 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1431 if (status_len == 0) {
1432 nt_status = filename_convert(ctx, conn,
1433 req->flags2 & FLAGS2_DFS_PATHNAMES,
1434 path,
1435 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1436 &mask_contains_wcard,
1437 &smb_fname);
1438 if (!NT_STATUS_IS_OK(nt_status)) {
1439 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1440 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1441 ERRSRV, ERRbadpath);
1442 goto out;
1444 reply_nterror(req, nt_status);
1445 goto out;
1448 directory = smb_fname->base_name;
1450 p = strrchr_m(directory,'/');
1451 if ((p != NULL) && (*directory != '/')) {
1452 mask = p + 1;
1453 directory = talloc_strndup(ctx, directory,
1454 PTR_DIFF(p, directory));
1455 } else {
1456 mask = directory;
1457 directory = talloc_strdup(ctx,".");
1460 if (!directory) {
1461 reply_nterror(req, NT_STATUS_NO_MEMORY);
1462 goto out;
1465 memset((char *)status,'\0',21);
1466 SCVAL(status,0,(dirtype & 0x1F));
1468 nt_status = dptr_create(conn,
1469 NULL, /* fsp */
1470 directory,
1471 True,
1472 expect_close,
1473 req->smbpid,
1474 mask,
1475 mask_contains_wcard,
1476 dirtype,
1477 &dirptr);
1478 if (!NT_STATUS_IS_OK(nt_status)) {
1479 reply_nterror(req, nt_status);
1480 goto out;
1482 dptr_num = dptr_dnum(dirptr);
1483 } else {
1484 int status_dirtype;
1485 const char *dirpath;
1487 memcpy(status,p,21);
1488 status_dirtype = CVAL(status,0) & 0x1F;
1489 if (status_dirtype != (dirtype & 0x1F)) {
1490 dirtype = status_dirtype;
1493 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1494 if (!dirptr) {
1495 goto SearchEmpty;
1497 dirpath = dptr_path(sconn, dptr_num);
1498 directory = talloc_strdup(ctx, dirpath);
1499 if (!directory) {
1500 reply_nterror(req, NT_STATUS_NO_MEMORY);
1501 goto out;
1504 mask = dptr_wcard(sconn, dptr_num);
1505 if (!mask) {
1506 goto SearchEmpty;
1509 * For a 'continue' search we have no string. So
1510 * check from the initial saved string.
1512 mask_contains_wcard = ms_has_wild(mask);
1513 dirtype = dptr_attr(sconn, dptr_num);
1516 DEBUG(4,("dptr_num is %d\n",dptr_num));
1518 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1519 dptr_init_search_op(dirptr);
1521 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1522 char buf[DIR_STRUCT_SIZE];
1523 memcpy(buf,status,21);
1524 if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1525 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1526 reply_nterror(req, NT_STATUS_NO_MEMORY);
1527 goto out;
1529 dptr_fill(sconn, buf+12,dptr_num);
1530 if (dptr_zero(buf+12) && (status_len==0)) {
1531 numentries = 1;
1532 } else {
1533 numentries = 0;
1535 if (message_push_blob(&req->outbuf,
1536 data_blob_const(buf, sizeof(buf)))
1537 == -1) {
1538 reply_nterror(req, NT_STATUS_NO_MEMORY);
1539 goto out;
1541 } else {
1542 unsigned int i;
1543 maxentries = MIN(
1544 maxentries,
1545 ((BUFFER_SIZE -
1546 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1547 /DIR_STRUCT_SIZE));
1549 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1550 directory,lp_dontdescend(SNUM(conn))));
1551 if (in_list(directory, lp_dontdescend(SNUM(conn)),True)) {
1552 check_descend = True;
1555 for (i=numentries;(i<maxentries) && !finished;i++) {
1556 finished = !get_dir_entry(ctx,
1557 dirptr,
1558 mask,
1559 dirtype,
1560 &fname,
1561 &size,
1562 &mode,
1563 &date,
1564 check_descend,
1565 ask_sharemode);
1566 if (!finished) {
1567 char buf[DIR_STRUCT_SIZE];
1568 memcpy(buf,status,21);
1569 if (!make_dir_struct(ctx,
1570 buf,
1571 mask,
1572 fname,
1573 size,
1574 mode,
1575 convert_timespec_to_time_t(date),
1576 !allow_long_path_components)) {
1577 reply_nterror(req, NT_STATUS_NO_MEMORY);
1578 goto out;
1580 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1581 break;
1583 if (message_push_blob(&req->outbuf,
1584 data_blob_const(buf, sizeof(buf)))
1585 == -1) {
1586 reply_nterror(req, NT_STATUS_NO_MEMORY);
1587 goto out;
1589 numentries++;
1594 SearchEmpty:
1596 /* If we were called as SMBffirst with smb_search_id == NULL
1597 and no entries were found then return error and close dirptr
1598 (X/Open spec) */
1600 if (numentries == 0) {
1601 dptr_close(sconn, &dptr_num);
1602 } else if(expect_close && status_len == 0) {
1603 /* Close the dptr - we know it's gone */
1604 dptr_close(sconn, &dptr_num);
1607 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1608 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1609 dptr_close(sconn, &dptr_num);
1612 if ((numentries == 0) && !mask_contains_wcard) {
1613 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1614 goto out;
1617 SSVAL(req->outbuf,smb_vwv0,numentries);
1618 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1619 SCVAL(smb_buf(req->outbuf),0,5);
1620 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1622 /* The replies here are never long name. */
1623 SSVAL(req->outbuf, smb_flg2,
1624 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1625 if (!allow_long_path_components) {
1626 SSVAL(req->outbuf, smb_flg2,
1627 SVAL(req->outbuf, smb_flg2)
1628 & (~FLAGS2_LONG_PATH_COMPONENTS));
1631 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1632 SSVAL(req->outbuf, smb_flg2,
1633 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1635 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1636 smb_fn_name(req->cmd),
1637 mask,
1638 directory,
1639 dirtype,
1640 numentries,
1641 maxentries ));
1642 out:
1643 TALLOC_FREE(directory);
1644 TALLOC_FREE(smb_fname);
1645 END_PROFILE(SMBsearch);
1646 return;
1649 /****************************************************************************
1650 Reply to a fclose (stop directory search).
1651 ****************************************************************************/
1653 void reply_fclose(struct smb_request *req)
1655 int status_len;
1656 char status[21];
1657 int dptr_num= -2;
1658 const char *p;
1659 char *path = NULL;
1660 NTSTATUS err;
1661 bool path_contains_wcard = False;
1662 TALLOC_CTX *ctx = talloc_tos();
1663 struct smbd_server_connection *sconn = req->sconn;
1665 START_PROFILE(SMBfclose);
1667 if (lp_posix_pathnames()) {
1668 reply_unknown_new(req, req->cmd);
1669 END_PROFILE(SMBfclose);
1670 return;
1673 p = (const char *)req->buf + 1;
1674 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1675 &err, &path_contains_wcard);
1676 if (!NT_STATUS_IS_OK(err)) {
1677 reply_nterror(req, err);
1678 END_PROFILE(SMBfclose);
1679 return;
1681 p++;
1682 status_len = SVAL(p,0);
1683 p += 2;
1685 if (status_len == 0) {
1686 reply_force_doserror(req, ERRSRV, ERRsrverror);
1687 END_PROFILE(SMBfclose);
1688 return;
1691 memcpy(status,p,21);
1693 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1694 /* Close the dptr - we know it's gone */
1695 dptr_close(sconn, &dptr_num);
1698 reply_outbuf(req, 1, 0);
1699 SSVAL(req->outbuf,smb_vwv0,0);
1701 DEBUG(3,("search close\n"));
1703 END_PROFILE(SMBfclose);
1704 return;
1707 /****************************************************************************
1708 Reply to an open.
1709 ****************************************************************************/
1711 void reply_open(struct smb_request *req)
1713 connection_struct *conn = req->conn;
1714 struct smb_filename *smb_fname = NULL;
1715 char *fname = NULL;
1716 uint32 fattr=0;
1717 SMB_OFF_T size = 0;
1718 time_t mtime=0;
1719 int info;
1720 files_struct *fsp;
1721 int oplock_request;
1722 int deny_mode;
1723 uint32 dos_attr;
1724 uint32 access_mask;
1725 uint32 share_mode;
1726 uint32 create_disposition;
1727 uint32 create_options = 0;
1728 uint32_t private_flags = 0;
1729 NTSTATUS status;
1730 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1731 TALLOC_CTX *ctx = talloc_tos();
1733 START_PROFILE(SMBopen);
1735 if (req->wct < 2) {
1736 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1737 goto out;
1740 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1741 deny_mode = SVAL(req->vwv+0, 0);
1742 dos_attr = SVAL(req->vwv+1, 0);
1744 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1745 STR_TERMINATE, &status);
1746 if (!NT_STATUS_IS_OK(status)) {
1747 reply_nterror(req, status);
1748 goto out;
1751 status = filename_convert(ctx,
1752 conn,
1753 req->flags2 & FLAGS2_DFS_PATHNAMES,
1754 fname,
1756 NULL,
1757 &smb_fname);
1758 if (!NT_STATUS_IS_OK(status)) {
1759 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1760 reply_botherror(req,
1761 NT_STATUS_PATH_NOT_COVERED,
1762 ERRSRV, ERRbadpath);
1763 goto out;
1765 reply_nterror(req, status);
1766 goto out;
1769 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1770 OPENX_FILE_EXISTS_OPEN, &access_mask,
1771 &share_mode, &create_disposition,
1772 &create_options, &private_flags)) {
1773 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1774 goto out;
1777 status = SMB_VFS_CREATE_FILE(
1778 conn, /* conn */
1779 req, /* req */
1780 0, /* root_dir_fid */
1781 smb_fname, /* fname */
1782 access_mask, /* access_mask */
1783 share_mode, /* share_access */
1784 create_disposition, /* create_disposition*/
1785 create_options, /* create_options */
1786 dos_attr, /* file_attributes */
1787 oplock_request, /* oplock_request */
1788 0, /* allocation_size */
1789 private_flags,
1790 NULL, /* sd */
1791 NULL, /* ea_list */
1792 &fsp, /* result */
1793 &info); /* pinfo */
1795 if (!NT_STATUS_IS_OK(status)) {
1796 if (open_was_deferred(req->mid)) {
1797 /* We have re-scheduled this call. */
1798 goto out;
1800 reply_openerror(req, status);
1801 goto out;
1804 size = smb_fname->st.st_ex_size;
1805 fattr = dos_mode(conn, smb_fname);
1807 /* Deal with other possible opens having a modified
1808 write time. JRA. */
1809 if (ask_sharemode) {
1810 struct timespec write_time_ts;
1812 ZERO_STRUCT(write_time_ts);
1813 get_file_infos(fsp->file_id, 0, NULL, &write_time_ts);
1814 if (!null_timespec(write_time_ts)) {
1815 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1819 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1821 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1822 DEBUG(3,("attempt to open a directory %s\n",
1823 fsp_str_dbg(fsp)));
1824 close_file(req, fsp, ERROR_CLOSE);
1825 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1826 ERRDOS, ERRnoaccess);
1827 goto out;
1830 reply_outbuf(req, 7, 0);
1831 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1832 SSVAL(req->outbuf,smb_vwv1,fattr);
1833 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1834 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1835 } else {
1836 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1838 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1839 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1841 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1842 SCVAL(req->outbuf,smb_flg,
1843 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1846 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1847 SCVAL(req->outbuf,smb_flg,
1848 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1850 out:
1851 TALLOC_FREE(smb_fname);
1852 END_PROFILE(SMBopen);
1853 return;
1856 /****************************************************************************
1857 Reply to an open and X.
1858 ****************************************************************************/
1860 void reply_open_and_X(struct smb_request *req)
1862 connection_struct *conn = req->conn;
1863 struct smb_filename *smb_fname = NULL;
1864 char *fname = NULL;
1865 uint16 open_flags;
1866 int deny_mode;
1867 uint32 smb_attr;
1868 /* Breakout the oplock request bits so we can set the
1869 reply bits separately. */
1870 int ex_oplock_request;
1871 int core_oplock_request;
1872 int oplock_request;
1873 #if 0
1874 int smb_sattr = SVAL(req->vwv+4, 0);
1875 uint32 smb_time = make_unix_date3(req->vwv+6);
1876 #endif
1877 int smb_ofun;
1878 uint32 fattr=0;
1879 int mtime=0;
1880 int smb_action = 0;
1881 files_struct *fsp;
1882 NTSTATUS status;
1883 uint64_t allocation_size;
1884 ssize_t retval = -1;
1885 uint32 access_mask;
1886 uint32 share_mode;
1887 uint32 create_disposition;
1888 uint32 create_options = 0;
1889 uint32_t private_flags = 0;
1890 TALLOC_CTX *ctx = talloc_tos();
1892 START_PROFILE(SMBopenX);
1894 if (req->wct < 15) {
1895 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1896 goto out;
1899 open_flags = SVAL(req->vwv+2, 0);
1900 deny_mode = SVAL(req->vwv+3, 0);
1901 smb_attr = SVAL(req->vwv+5, 0);
1902 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1903 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1904 oplock_request = ex_oplock_request | core_oplock_request;
1905 smb_ofun = SVAL(req->vwv+8, 0);
1906 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1908 /* If it's an IPC, pass off the pipe handler. */
1909 if (IS_IPC(conn)) {
1910 if (lp_nt_pipe_support()) {
1911 reply_open_pipe_and_X(conn, req);
1912 } else {
1913 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1915 goto out;
1918 /* XXXX we need to handle passed times, sattr and flags */
1919 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1920 STR_TERMINATE, &status);
1921 if (!NT_STATUS_IS_OK(status)) {
1922 reply_nterror(req, status);
1923 goto out;
1926 status = filename_convert(ctx,
1927 conn,
1928 req->flags2 & FLAGS2_DFS_PATHNAMES,
1929 fname,
1931 NULL,
1932 &smb_fname);
1933 if (!NT_STATUS_IS_OK(status)) {
1934 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1935 reply_botherror(req,
1936 NT_STATUS_PATH_NOT_COVERED,
1937 ERRSRV, ERRbadpath);
1938 goto out;
1940 reply_nterror(req, status);
1941 goto out;
1944 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1945 smb_ofun,
1946 &access_mask, &share_mode,
1947 &create_disposition,
1948 &create_options,
1949 &private_flags)) {
1950 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1951 goto out;
1954 status = SMB_VFS_CREATE_FILE(
1955 conn, /* conn */
1956 req, /* req */
1957 0, /* root_dir_fid */
1958 smb_fname, /* fname */
1959 access_mask, /* access_mask */
1960 share_mode, /* share_access */
1961 create_disposition, /* create_disposition*/
1962 create_options, /* create_options */
1963 smb_attr, /* file_attributes */
1964 oplock_request, /* oplock_request */
1965 0, /* allocation_size */
1966 private_flags,
1967 NULL, /* sd */
1968 NULL, /* ea_list */
1969 &fsp, /* result */
1970 &smb_action); /* pinfo */
1972 if (!NT_STATUS_IS_OK(status)) {
1973 if (open_was_deferred(req->mid)) {
1974 /* We have re-scheduled this call. */
1975 goto out;
1977 reply_openerror(req, status);
1978 goto out;
1981 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1982 if the file is truncated or created. */
1983 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1984 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1985 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1986 close_file(req, fsp, ERROR_CLOSE);
1987 reply_nterror(req, NT_STATUS_DISK_FULL);
1988 goto out;
1990 retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1991 if (retval < 0) {
1992 close_file(req, fsp, ERROR_CLOSE);
1993 reply_nterror(req, NT_STATUS_DISK_FULL);
1994 goto out;
1996 status = vfs_stat_fsp(fsp);
1997 if (!NT_STATUS_IS_OK(status)) {
1998 close_file(req, fsp, ERROR_CLOSE);
1999 reply_nterror(req, status);
2000 goto out;
2004 fattr = dos_mode(conn, fsp->fsp_name);
2005 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2006 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2007 close_file(req, fsp, ERROR_CLOSE);
2008 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2009 goto out;
2012 /* If the caller set the extended oplock request bit
2013 and we granted one (by whatever means) - set the
2014 correct bit for extended oplock reply.
2017 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2018 smb_action |= EXTENDED_OPLOCK_GRANTED;
2021 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2022 smb_action |= EXTENDED_OPLOCK_GRANTED;
2025 /* If the caller set the core oplock request bit
2026 and we granted one (by whatever means) - set the
2027 correct bit for core oplock reply.
2030 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2031 reply_outbuf(req, 19, 0);
2032 } else {
2033 reply_outbuf(req, 15, 0);
2036 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2037 SCVAL(req->outbuf, smb_flg,
2038 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2041 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2042 SCVAL(req->outbuf, smb_flg,
2043 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2046 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2047 SSVAL(req->outbuf,smb_vwv3,fattr);
2048 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2049 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2050 } else {
2051 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2053 SIVAL(req->outbuf,smb_vwv6,(uint32)fsp->fsp_name->st.st_ex_size);
2054 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2055 SSVAL(req->outbuf,smb_vwv11,smb_action);
2057 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2058 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2061 chain_reply(req);
2062 out:
2063 TALLOC_FREE(smb_fname);
2064 END_PROFILE(SMBopenX);
2065 return;
2068 /****************************************************************************
2069 Reply to a SMBulogoffX.
2070 ****************************************************************************/
2072 void reply_ulogoffX(struct smb_request *req)
2074 struct smbd_server_connection *sconn = req->sconn;
2075 user_struct *vuser;
2077 START_PROFILE(SMBulogoffX);
2079 vuser = get_valid_user_struct(sconn, req->vuid);
2081 if(vuser == NULL) {
2082 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2083 req->vuid));
2086 /* in user level security we are supposed to close any files
2087 open by this user */
2088 if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2089 file_close_user(sconn, req->vuid);
2092 invalidate_vuid(sconn, req->vuid);
2094 reply_outbuf(req, 2, 0);
2096 DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2098 END_PROFILE(SMBulogoffX);
2099 req->vuid = UID_FIELD_INVALID;
2100 chain_reply(req);
2103 /****************************************************************************
2104 Reply to a mknew or a create.
2105 ****************************************************************************/
2107 void reply_mknew(struct smb_request *req)
2109 connection_struct *conn = req->conn;
2110 struct smb_filename *smb_fname = NULL;
2111 char *fname = NULL;
2112 uint32 fattr = 0;
2113 struct smb_file_time ft;
2114 files_struct *fsp;
2115 int oplock_request = 0;
2116 NTSTATUS status;
2117 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2118 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2119 uint32 create_disposition;
2120 uint32 create_options = 0;
2121 TALLOC_CTX *ctx = talloc_tos();
2123 START_PROFILE(SMBcreate);
2124 ZERO_STRUCT(ft);
2126 if (req->wct < 3) {
2127 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2128 goto out;
2131 fattr = SVAL(req->vwv+0, 0);
2132 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2134 /* mtime. */
2135 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2137 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2138 STR_TERMINATE, &status);
2139 if (!NT_STATUS_IS_OK(status)) {
2140 reply_nterror(req, status);
2141 goto out;
2144 status = filename_convert(ctx,
2145 conn,
2146 req->flags2 & FLAGS2_DFS_PATHNAMES,
2147 fname,
2149 NULL,
2150 &smb_fname);
2151 if (!NT_STATUS_IS_OK(status)) {
2152 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2153 reply_botherror(req,
2154 NT_STATUS_PATH_NOT_COVERED,
2155 ERRSRV, ERRbadpath);
2156 goto out;
2158 reply_nterror(req, status);
2159 goto out;
2162 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2163 DEBUG(0,("Attempt to create file (%s) with volid set - "
2164 "please report this\n",
2165 smb_fname_str_dbg(smb_fname)));
2168 if(req->cmd == SMBmknew) {
2169 /* We should fail if file exists. */
2170 create_disposition = FILE_CREATE;
2171 } else {
2172 /* Create if file doesn't exist, truncate if it does. */
2173 create_disposition = FILE_OVERWRITE_IF;
2176 status = SMB_VFS_CREATE_FILE(
2177 conn, /* conn */
2178 req, /* req */
2179 0, /* root_dir_fid */
2180 smb_fname, /* fname */
2181 access_mask, /* access_mask */
2182 share_mode, /* share_access */
2183 create_disposition, /* create_disposition*/
2184 create_options, /* create_options */
2185 fattr, /* file_attributes */
2186 oplock_request, /* oplock_request */
2187 0, /* allocation_size */
2188 0, /* private_flags */
2189 NULL, /* sd */
2190 NULL, /* ea_list */
2191 &fsp, /* result */
2192 NULL); /* pinfo */
2194 if (!NT_STATUS_IS_OK(status)) {
2195 if (open_was_deferred(req->mid)) {
2196 /* We have re-scheduled this call. */
2197 goto out;
2199 reply_openerror(req, status);
2200 goto out;
2203 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2204 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2205 if (!NT_STATUS_IS_OK(status)) {
2206 END_PROFILE(SMBcreate);
2207 goto out;
2210 reply_outbuf(req, 1, 0);
2211 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2213 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2214 SCVAL(req->outbuf,smb_flg,
2215 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2218 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2219 SCVAL(req->outbuf,smb_flg,
2220 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2223 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2224 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2225 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2226 (unsigned int)fattr));
2228 out:
2229 TALLOC_FREE(smb_fname);
2230 END_PROFILE(SMBcreate);
2231 return;
2234 /****************************************************************************
2235 Reply to a create temporary file.
2236 ****************************************************************************/
2238 void reply_ctemp(struct smb_request *req)
2240 connection_struct *conn = req->conn;
2241 struct smb_filename *smb_fname = NULL;
2242 char *fname = NULL;
2243 uint32 fattr;
2244 files_struct *fsp;
2245 int oplock_request;
2246 int tmpfd;
2247 char *s;
2248 NTSTATUS status;
2249 TALLOC_CTX *ctx = talloc_tos();
2251 START_PROFILE(SMBctemp);
2253 if (req->wct < 3) {
2254 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2255 goto out;
2258 fattr = SVAL(req->vwv+0, 0);
2259 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2261 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2262 STR_TERMINATE, &status);
2263 if (!NT_STATUS_IS_OK(status)) {
2264 reply_nterror(req, status);
2265 goto out;
2267 if (*fname) {
2268 fname = talloc_asprintf(ctx,
2269 "%s/TMXXXXXX",
2270 fname);
2271 } else {
2272 fname = talloc_strdup(ctx, "TMXXXXXX");
2275 if (!fname) {
2276 reply_nterror(req, NT_STATUS_NO_MEMORY);
2277 goto out;
2280 status = filename_convert(ctx, conn,
2281 req->flags2 & FLAGS2_DFS_PATHNAMES,
2282 fname,
2284 NULL,
2285 &smb_fname);
2286 if (!NT_STATUS_IS_OK(status)) {
2287 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2288 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2289 ERRSRV, ERRbadpath);
2290 goto out;
2292 reply_nterror(req, status);
2293 goto out;
2296 tmpfd = mkstemp(smb_fname->base_name);
2297 if (tmpfd == -1) {
2298 reply_nterror(req, map_nt_error_from_unix(errno));
2299 goto out;
2302 SMB_VFS_STAT(conn, smb_fname);
2304 /* We should fail if file does not exist. */
2305 status = SMB_VFS_CREATE_FILE(
2306 conn, /* conn */
2307 req, /* req */
2308 0, /* root_dir_fid */
2309 smb_fname, /* fname */
2310 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2311 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2312 FILE_OPEN, /* create_disposition*/
2313 0, /* create_options */
2314 fattr, /* file_attributes */
2315 oplock_request, /* oplock_request */
2316 0, /* allocation_size */
2317 0, /* private_flags */
2318 NULL, /* sd */
2319 NULL, /* ea_list */
2320 &fsp, /* result */
2321 NULL); /* pinfo */
2323 /* close fd from mkstemp() */
2324 close(tmpfd);
2326 if (!NT_STATUS_IS_OK(status)) {
2327 if (open_was_deferred(req->mid)) {
2328 /* We have re-scheduled this call. */
2329 goto out;
2331 reply_openerror(req, status);
2332 goto out;
2335 reply_outbuf(req, 1, 0);
2336 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2338 /* the returned filename is relative to the directory */
2339 s = strrchr_m(fsp->fsp_name->base_name, '/');
2340 if (!s) {
2341 s = fsp->fsp_name->base_name;
2342 } else {
2343 s++;
2346 #if 0
2347 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2348 thing in the byte section. JRA */
2349 SSVALS(p, 0, -1); /* what is this? not in spec */
2350 #endif
2351 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2352 == -1) {
2353 reply_nterror(req, NT_STATUS_NO_MEMORY);
2354 goto out;
2357 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2358 SCVAL(req->outbuf, smb_flg,
2359 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2362 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2363 SCVAL(req->outbuf, smb_flg,
2364 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2367 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2368 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2369 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2370 out:
2371 TALLOC_FREE(smb_fname);
2372 END_PROFILE(SMBctemp);
2373 return;
2376 /*******************************************************************
2377 Check if a user is allowed to rename a file.
2378 ********************************************************************/
2380 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2381 uint16 dirtype)
2383 if (!CAN_WRITE(conn)) {
2384 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2387 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2388 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2389 /* Only bother to read the DOS attribute if we might deny the
2390 rename on the grounds of attribute missmatch. */
2391 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2392 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2393 return NT_STATUS_NO_SUCH_FILE;
2397 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2398 if (fsp->posix_open) {
2399 return NT_STATUS_OK;
2402 /* If no pathnames are open below this
2403 directory, allow the rename. */
2405 if (file_find_subpath(fsp)) {
2406 return NT_STATUS_ACCESS_DENIED;
2408 return NT_STATUS_OK;
2411 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2412 return NT_STATUS_OK;
2415 return NT_STATUS_ACCESS_DENIED;
2418 /*******************************************************************
2419 * unlink a file with all relevant access checks
2420 *******************************************************************/
2422 static NTSTATUS do_unlink(connection_struct *conn,
2423 struct smb_request *req,
2424 struct smb_filename *smb_fname,
2425 uint32 dirtype)
2427 uint32 fattr;
2428 files_struct *fsp;
2429 uint32 dirtype_orig = dirtype;
2430 NTSTATUS status;
2431 int ret;
2432 bool posix_paths = lp_posix_pathnames();
2434 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2435 smb_fname_str_dbg(smb_fname),
2436 dirtype));
2438 if (!CAN_WRITE(conn)) {
2439 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2442 if (posix_paths) {
2443 ret = SMB_VFS_LSTAT(conn, smb_fname);
2444 } else {
2445 ret = SMB_VFS_STAT(conn, smb_fname);
2447 if (ret != 0) {
2448 return map_nt_error_from_unix(errno);
2451 fattr = dos_mode(conn, smb_fname);
2453 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2454 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2457 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2458 if (!dirtype) {
2459 return NT_STATUS_NO_SUCH_FILE;
2462 if (!dir_check_ftype(conn, fattr, dirtype)) {
2463 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2464 return NT_STATUS_FILE_IS_A_DIRECTORY;
2466 return NT_STATUS_NO_SUCH_FILE;
2469 if (dirtype_orig & 0x8000) {
2470 /* These will never be set for POSIX. */
2471 return NT_STATUS_NO_SUCH_FILE;
2474 #if 0
2475 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2476 return NT_STATUS_FILE_IS_A_DIRECTORY;
2479 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2480 return NT_STATUS_NO_SUCH_FILE;
2483 if (dirtype & 0xFF00) {
2484 /* These will never be set for POSIX. */
2485 return NT_STATUS_NO_SUCH_FILE;
2488 dirtype &= 0xFF;
2489 if (!dirtype) {
2490 return NT_STATUS_NO_SUCH_FILE;
2493 /* Can't delete a directory. */
2494 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2495 return NT_STATUS_FILE_IS_A_DIRECTORY;
2497 #endif
2499 #if 0 /* JRATEST */
2500 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2501 return NT_STATUS_OBJECT_NAME_INVALID;
2502 #endif /* JRATEST */
2504 /* On open checks the open itself will check the share mode, so
2505 don't do it here as we'll get it wrong. */
2507 status = SMB_VFS_CREATE_FILE
2508 (conn, /* conn */
2509 req, /* req */
2510 0, /* root_dir_fid */
2511 smb_fname, /* fname */
2512 DELETE_ACCESS, /* access_mask */
2513 FILE_SHARE_NONE, /* share_access */
2514 FILE_OPEN, /* create_disposition*/
2515 FILE_NON_DIRECTORY_FILE, /* create_options */
2516 /* file_attributes */
2517 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2518 FILE_ATTRIBUTE_NORMAL,
2519 0, /* oplock_request */
2520 0, /* allocation_size */
2521 0, /* private_flags */
2522 NULL, /* sd */
2523 NULL, /* ea_list */
2524 &fsp, /* result */
2525 NULL); /* pinfo */
2527 if (!NT_STATUS_IS_OK(status)) {
2528 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2529 nt_errstr(status)));
2530 return status;
2533 status = can_set_delete_on_close(fsp, fattr);
2534 if (!NT_STATUS_IS_OK(status)) {
2535 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2536 "(%s)\n",
2537 smb_fname_str_dbg(smb_fname),
2538 nt_errstr(status)));
2539 close_file(req, fsp, NORMAL_CLOSE);
2540 return status;
2543 /* The set is across all open files on this dev/inode pair. */
2544 if (!set_delete_on_close(fsp, true,
2545 conn->session_info->security_token,
2546 &conn->session_info->utok)) {
2547 close_file(req, fsp, NORMAL_CLOSE);
2548 return NT_STATUS_ACCESS_DENIED;
2551 return close_file(req, fsp, NORMAL_CLOSE);
2554 /****************************************************************************
2555 The guts of the unlink command, split out so it may be called by the NT SMB
2556 code.
2557 ****************************************************************************/
2559 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2560 uint32 dirtype, struct smb_filename *smb_fname,
2561 bool has_wild)
2563 char *fname_dir = NULL;
2564 char *fname_mask = NULL;
2565 int count=0;
2566 NTSTATUS status = NT_STATUS_OK;
2567 TALLOC_CTX *ctx = talloc_tos();
2569 /* Split up the directory from the filename/mask. */
2570 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2571 &fname_dir, &fname_mask);
2572 if (!NT_STATUS_IS_OK(status)) {
2573 goto out;
2577 * We should only check the mangled cache
2578 * here if unix_convert failed. This means
2579 * that the path in 'mask' doesn't exist
2580 * on the file system and so we need to look
2581 * for a possible mangle. This patch from
2582 * Tine Smukavec <valentin.smukavec@hermes.si>.
2585 if (!VALID_STAT(smb_fname->st) &&
2586 mangle_is_mangled(fname_mask, conn->params)) {
2587 char *new_mask = NULL;
2588 mangle_lookup_name_from_8_3(ctx, fname_mask,
2589 &new_mask, conn->params);
2590 if (new_mask) {
2591 TALLOC_FREE(fname_mask);
2592 fname_mask = new_mask;
2596 if (!has_wild) {
2599 * Only one file needs to be unlinked. Append the mask back
2600 * onto the directory.
2602 TALLOC_FREE(smb_fname->base_name);
2603 if (ISDOT(fname_dir)) {
2604 /* Ensure we use canonical names on open. */
2605 smb_fname->base_name = talloc_asprintf(smb_fname,
2606 "%s",
2607 fname_mask);
2608 } else {
2609 smb_fname->base_name = talloc_asprintf(smb_fname,
2610 "%s/%s",
2611 fname_dir,
2612 fname_mask);
2614 if (!smb_fname->base_name) {
2615 status = NT_STATUS_NO_MEMORY;
2616 goto out;
2618 if (dirtype == 0) {
2619 dirtype = FILE_ATTRIBUTE_NORMAL;
2622 status = check_name(conn, smb_fname->base_name);
2623 if (!NT_STATUS_IS_OK(status)) {
2624 goto out;
2627 status = do_unlink(conn, req, smb_fname, dirtype);
2628 if (!NT_STATUS_IS_OK(status)) {
2629 goto out;
2632 count++;
2633 } else {
2634 struct smb_Dir *dir_hnd = NULL;
2635 long offset = 0;
2636 const char *dname = NULL;
2637 char *talloced = NULL;
2639 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
2640 status = NT_STATUS_OBJECT_NAME_INVALID;
2641 goto out;
2644 if (strequal(fname_mask,"????????.???")) {
2645 TALLOC_FREE(fname_mask);
2646 fname_mask = talloc_strdup(ctx, "*");
2647 if (!fname_mask) {
2648 status = NT_STATUS_NO_MEMORY;
2649 goto out;
2653 status = check_name(conn, fname_dir);
2654 if (!NT_STATUS_IS_OK(status)) {
2655 goto out;
2658 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2659 dirtype);
2660 if (dir_hnd == NULL) {
2661 status = map_nt_error_from_unix(errno);
2662 goto out;
2665 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2666 the pattern matches against the long name, otherwise the short name
2667 We don't implement this yet XXXX
2670 status = NT_STATUS_NO_SUCH_FILE;
2672 while ((dname = ReadDirName(dir_hnd, &offset,
2673 &smb_fname->st, &talloced))) {
2674 TALLOC_CTX *frame = talloc_stackframe();
2676 if (!is_visible_file(conn, fname_dir, dname,
2677 &smb_fname->st, true)) {
2678 TALLOC_FREE(frame);
2679 TALLOC_FREE(talloced);
2680 continue;
2683 /* Quick check for "." and ".." */
2684 if (ISDOT(dname) || ISDOTDOT(dname)) {
2685 TALLOC_FREE(frame);
2686 TALLOC_FREE(talloced);
2687 continue;
2690 if(!mask_match(dname, fname_mask,
2691 conn->case_sensitive)) {
2692 TALLOC_FREE(frame);
2693 TALLOC_FREE(talloced);
2694 continue;
2697 TALLOC_FREE(smb_fname->base_name);
2698 if (ISDOT(fname_dir)) {
2699 /* Ensure we use canonical names on open. */
2700 smb_fname->base_name =
2701 talloc_asprintf(smb_fname, "%s",
2702 dname);
2703 } else {
2704 smb_fname->base_name =
2705 talloc_asprintf(smb_fname, "%s/%s",
2706 fname_dir, dname);
2709 if (!smb_fname->base_name) {
2710 TALLOC_FREE(dir_hnd);
2711 status = NT_STATUS_NO_MEMORY;
2712 TALLOC_FREE(frame);
2713 TALLOC_FREE(talloced);
2714 goto out;
2717 status = check_name(conn, smb_fname->base_name);
2718 if (!NT_STATUS_IS_OK(status)) {
2719 TALLOC_FREE(dir_hnd);
2720 TALLOC_FREE(frame);
2721 TALLOC_FREE(talloced);
2722 goto out;
2725 status = do_unlink(conn, req, smb_fname, dirtype);
2726 if (!NT_STATUS_IS_OK(status)) {
2727 TALLOC_FREE(frame);
2728 TALLOC_FREE(talloced);
2729 continue;
2732 count++;
2733 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2734 smb_fname->base_name));
2736 TALLOC_FREE(frame);
2737 TALLOC_FREE(talloced);
2739 TALLOC_FREE(dir_hnd);
2742 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2743 status = map_nt_error_from_unix(errno);
2746 out:
2747 TALLOC_FREE(fname_dir);
2748 TALLOC_FREE(fname_mask);
2749 return status;
2752 /****************************************************************************
2753 Reply to a unlink
2754 ****************************************************************************/
2756 void reply_unlink(struct smb_request *req)
2758 connection_struct *conn = req->conn;
2759 char *name = NULL;
2760 struct smb_filename *smb_fname = NULL;
2761 uint32 dirtype;
2762 NTSTATUS status;
2763 bool path_contains_wcard = False;
2764 TALLOC_CTX *ctx = talloc_tos();
2766 START_PROFILE(SMBunlink);
2768 if (req->wct < 1) {
2769 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2770 goto out;
2773 dirtype = SVAL(req->vwv+0, 0);
2775 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2776 STR_TERMINATE, &status,
2777 &path_contains_wcard);
2778 if (!NT_STATUS_IS_OK(status)) {
2779 reply_nterror(req, status);
2780 goto out;
2783 status = filename_convert(ctx, conn,
2784 req->flags2 & FLAGS2_DFS_PATHNAMES,
2785 name,
2786 UCF_COND_ALLOW_WCARD_LCOMP,
2787 &path_contains_wcard,
2788 &smb_fname);
2789 if (!NT_STATUS_IS_OK(status)) {
2790 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2791 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2792 ERRSRV, ERRbadpath);
2793 goto out;
2795 reply_nterror(req, status);
2796 goto out;
2799 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2801 status = unlink_internals(conn, req, dirtype, smb_fname,
2802 path_contains_wcard);
2803 if (!NT_STATUS_IS_OK(status)) {
2804 if (open_was_deferred(req->mid)) {
2805 /* We have re-scheduled this call. */
2806 goto out;
2808 reply_nterror(req, status);
2809 goto out;
2812 reply_outbuf(req, 0, 0);
2813 out:
2814 TALLOC_FREE(smb_fname);
2815 END_PROFILE(SMBunlink);
2816 return;
2819 /****************************************************************************
2820 Fail for readbraw.
2821 ****************************************************************************/
2823 static void fail_readraw(void)
2825 const char *errstr = talloc_asprintf(talloc_tos(),
2826 "FAIL ! reply_readbraw: socket write fail (%s)",
2827 strerror(errno));
2828 if (!errstr) {
2829 errstr = "";
2831 exit_server_cleanly(errstr);
2834 /****************************************************************************
2835 Fake (read/write) sendfile. Returns -1 on read or write fail.
2836 ****************************************************************************/
2838 ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread)
2840 size_t bufsize;
2841 size_t tosend = nread;
2842 char *buf;
2844 if (nread == 0) {
2845 return 0;
2848 bufsize = MIN(nread, 65536);
2850 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2851 return -1;
2854 while (tosend > 0) {
2855 ssize_t ret;
2856 size_t cur_read;
2858 if (tosend > bufsize) {
2859 cur_read = bufsize;
2860 } else {
2861 cur_read = tosend;
2863 ret = read_file(fsp,buf,startpos,cur_read);
2864 if (ret == -1) {
2865 SAFE_FREE(buf);
2866 return -1;
2869 /* If we had a short read, fill with zeros. */
2870 if (ret < cur_read) {
2871 memset(buf + ret, '\0', cur_read - ret);
2874 if (write_data(fsp->conn->sconn->sock, buf, cur_read)
2875 != cur_read) {
2876 char addr[INET6_ADDRSTRLEN];
2878 * Try and give an error message saying what
2879 * client failed.
2881 DEBUG(0, ("write_data failed for client %s. "
2882 "Error %s\n",
2883 get_peer_addr(fsp->conn->sconn->sock, addr,
2884 sizeof(addr)),
2885 strerror(errno)));
2886 SAFE_FREE(buf);
2887 return -1;
2889 tosend -= cur_read;
2890 startpos += cur_read;
2893 SAFE_FREE(buf);
2894 return (ssize_t)nread;
2897 /****************************************************************************
2898 Deal with the case of sendfile reading less bytes from the file than
2899 requested. Fill with zeros (all we can do).
2900 ****************************************************************************/
2902 void sendfile_short_send(files_struct *fsp,
2903 ssize_t nread,
2904 size_t headersize,
2905 size_t smb_maxcnt)
2907 #define SHORT_SEND_BUFSIZE 1024
2908 if (nread < headersize) {
2909 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2910 "header for file %s (%s). Terminating\n",
2911 fsp_str_dbg(fsp), strerror(errno)));
2912 exit_server_cleanly("sendfile_short_send failed");
2915 nread -= headersize;
2917 if (nread < smb_maxcnt) {
2918 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2919 if (!buf) {
2920 exit_server_cleanly("sendfile_short_send: "
2921 "malloc failed");
2924 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2925 "with zeros !\n", fsp_str_dbg(fsp)));
2927 while (nread < smb_maxcnt) {
2929 * We asked for the real file size and told sendfile
2930 * to not go beyond the end of the file. But it can
2931 * happen that in between our fstat call and the
2932 * sendfile call the file was truncated. This is very
2933 * bad because we have already announced the larger
2934 * number of bytes to the client.
2936 * The best we can do now is to send 0-bytes, just as
2937 * a read from a hole in a sparse file would do.
2939 * This should happen rarely enough that I don't care
2940 * about efficiency here :-)
2942 size_t to_write;
2944 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2945 if (write_data(fsp->conn->sconn->sock, buf, to_write)
2946 != to_write) {
2947 char addr[INET6_ADDRSTRLEN];
2949 * Try and give an error message saying what
2950 * client failed.
2952 DEBUG(0, ("write_data failed for client %s. "
2953 "Error %s\n",
2954 get_peer_addr(
2955 fsp->conn->sconn->sock, addr,
2956 sizeof(addr)),
2957 strerror(errno)));
2958 exit_server_cleanly("sendfile_short_send: "
2959 "write_data failed");
2961 nread += to_write;
2963 SAFE_FREE(buf);
2967 /****************************************************************************
2968 Return a readbraw error (4 bytes of zero).
2969 ****************************************************************************/
2971 static void reply_readbraw_error(struct smbd_server_connection *sconn)
2973 char header[4];
2975 SIVAL(header,0,0);
2977 smbd_lock_socket(sconn);
2978 if (write_data(sconn->sock,header,4) != 4) {
2979 char addr[INET6_ADDRSTRLEN];
2981 * Try and give an error message saying what
2982 * client failed.
2984 DEBUG(0, ("write_data failed for client %s. "
2985 "Error %s\n",
2986 get_peer_addr(sconn->sock, addr, sizeof(addr)),
2987 strerror(errno)));
2989 fail_readraw();
2991 smbd_unlock_socket(sconn);
2994 /****************************************************************************
2995 Use sendfile in readbraw.
2996 ****************************************************************************/
2998 static void send_file_readbraw(connection_struct *conn,
2999 struct smb_request *req,
3000 files_struct *fsp,
3001 SMB_OFF_T startpos,
3002 size_t nread,
3003 ssize_t mincount)
3005 struct smbd_server_connection *sconn = req->sconn;
3006 char *outbuf = NULL;
3007 ssize_t ret=0;
3010 * We can only use sendfile on a non-chained packet
3011 * but we can use on a non-oplocked file. tridge proved this
3012 * on a train in Germany :-). JRA.
3013 * reply_readbraw has already checked the length.
3016 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3017 (fsp->wcp == NULL) &&
3018 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3019 ssize_t sendfile_read = -1;
3020 char header[4];
3021 DATA_BLOB header_blob;
3023 _smb_setlen(header,nread);
3024 header_blob = data_blob_const(header, 4);
3026 sendfile_read = SMB_VFS_SENDFILE(sconn->sock, fsp,
3027 &header_blob, startpos,
3028 nread);
3029 if (sendfile_read == -1) {
3030 /* Returning ENOSYS means no data at all was sent.
3031 * Do this as a normal read. */
3032 if (errno == ENOSYS) {
3033 goto normal_readbraw;
3037 * Special hack for broken Linux with no working sendfile. If we
3038 * return EINTR we sent the header but not the rest of the data.
3039 * Fake this up by doing read/write calls.
3041 if (errno == EINTR) {
3042 /* Ensure we don't do this again. */
3043 set_use_sendfile(SNUM(conn), False);
3044 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3046 if (fake_sendfile(fsp, startpos, nread) == -1) {
3047 DEBUG(0,("send_file_readbraw: "
3048 "fake_sendfile failed for "
3049 "file %s (%s).\n",
3050 fsp_str_dbg(fsp),
3051 strerror(errno)));
3052 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3054 return;
3057 DEBUG(0,("send_file_readbraw: sendfile failed for "
3058 "file %s (%s). Terminating\n",
3059 fsp_str_dbg(fsp), strerror(errno)));
3060 exit_server_cleanly("send_file_readbraw sendfile failed");
3061 } else if (sendfile_read == 0) {
3063 * Some sendfile implementations return 0 to indicate
3064 * that there was a short read, but nothing was
3065 * actually written to the socket. In this case,
3066 * fallback to the normal read path so the header gets
3067 * the correct byte count.
3069 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3070 "bytes falling back to the normal read: "
3071 "%s\n", fsp_str_dbg(fsp)));
3072 goto normal_readbraw;
3075 /* Deal with possible short send. */
3076 if (sendfile_read != 4+nread) {
3077 sendfile_short_send(fsp, sendfile_read, 4, nread);
3079 return;
3082 normal_readbraw:
3084 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
3085 if (!outbuf) {
3086 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
3087 (unsigned)(nread+4)));
3088 reply_readbraw_error(sconn);
3089 return;
3092 if (nread > 0) {
3093 ret = read_file(fsp,outbuf+4,startpos,nread);
3094 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3095 if (ret < mincount)
3096 ret = 0;
3097 #else
3098 if (ret < nread)
3099 ret = 0;
3100 #endif
3103 _smb_setlen(outbuf,ret);
3104 if (write_data(sconn->sock, outbuf, 4+ret) != 4+ret) {
3105 char addr[INET6_ADDRSTRLEN];
3107 * Try and give an error message saying what
3108 * client failed.
3110 DEBUG(0, ("write_data failed for client %s. "
3111 "Error %s\n",
3112 get_peer_addr(fsp->conn->sconn->sock, addr,
3113 sizeof(addr)),
3114 strerror(errno)));
3116 fail_readraw();
3119 TALLOC_FREE(outbuf);
3122 /****************************************************************************
3123 Reply to a readbraw (core+ protocol).
3124 ****************************************************************************/
3126 void reply_readbraw(struct smb_request *req)
3128 connection_struct *conn = req->conn;
3129 struct smbd_server_connection *sconn = req->sconn;
3130 ssize_t maxcount,mincount;
3131 size_t nread = 0;
3132 SMB_OFF_T startpos;
3133 files_struct *fsp;
3134 struct lock_struct lock;
3135 SMB_OFF_T size = 0;
3137 START_PROFILE(SMBreadbraw);
3139 if (srv_is_signing_active(sconn) || req->encrypted) {
3140 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3141 "raw reads/writes are disallowed.");
3144 if (req->wct < 8) {
3145 reply_readbraw_error(sconn);
3146 END_PROFILE(SMBreadbraw);
3147 return;
3150 if (sconn->smb1.echo_handler.trusted_fde) {
3151 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3152 "'async smb echo handler = yes'\n"));
3153 reply_readbraw_error(sconn);
3154 END_PROFILE(SMBreadbraw);
3155 return;
3159 * Special check if an oplock break has been issued
3160 * and the readraw request croses on the wire, we must
3161 * return a zero length response here.
3164 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3167 * We have to do a check_fsp by hand here, as
3168 * we must always return 4 zero bytes on error,
3169 * not a NTSTATUS.
3172 if (!fsp || !conn || conn != fsp->conn ||
3173 req->vuid != fsp->vuid ||
3174 fsp->is_directory || fsp->fh->fd == -1) {
3176 * fsp could be NULL here so use the value from the packet. JRA.
3178 DEBUG(3,("reply_readbraw: fnum %d not valid "
3179 "- cache prime?\n",
3180 (int)SVAL(req->vwv+0, 0)));
3181 reply_readbraw_error(sconn);
3182 END_PROFILE(SMBreadbraw);
3183 return;
3186 /* Do a "by hand" version of CHECK_READ. */
3187 if (!(fsp->can_read ||
3188 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3189 (fsp->access_mask & FILE_EXECUTE)))) {
3190 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3191 (int)SVAL(req->vwv+0, 0)));
3192 reply_readbraw_error(sconn);
3193 END_PROFILE(SMBreadbraw);
3194 return;
3197 flush_write_cache(fsp, READRAW_FLUSH);
3199 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3200 if(req->wct == 10) {
3202 * This is a large offset (64 bit) read.
3204 #ifdef LARGE_SMB_OFF_T
3206 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3208 #else /* !LARGE_SMB_OFF_T */
3211 * Ensure we haven't been sent a >32 bit offset.
3214 if(IVAL(req->vwv+8, 0) != 0) {
3215 DEBUG(0,("reply_readbraw: large offset "
3216 "(%x << 32) used and we don't support "
3217 "64 bit offsets.\n",
3218 (unsigned int)IVAL(req->vwv+8, 0) ));
3219 reply_readbraw_error(sconn);
3220 END_PROFILE(SMBreadbraw);
3221 return;
3224 #endif /* LARGE_SMB_OFF_T */
3226 if(startpos < 0) {
3227 DEBUG(0,("reply_readbraw: negative 64 bit "
3228 "readraw offset (%.0f) !\n",
3229 (double)startpos ));
3230 reply_readbraw_error(sconn);
3231 END_PROFILE(SMBreadbraw);
3232 return;
3236 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3237 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3239 /* ensure we don't overrun the packet size */
3240 maxcount = MIN(65535,maxcount);
3242 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3243 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3244 &lock);
3246 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3247 reply_readbraw_error(sconn);
3248 END_PROFILE(SMBreadbraw);
3249 return;
3252 if (fsp_stat(fsp) == 0) {
3253 size = fsp->fsp_name->st.st_ex_size;
3256 if (startpos >= size) {
3257 nread = 0;
3258 } else {
3259 nread = MIN(maxcount,(size - startpos));
3262 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3263 if (nread < mincount)
3264 nread = 0;
3265 #endif
3267 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3268 "min=%lu nread=%lu\n",
3269 fsp->fnum, (double)startpos,
3270 (unsigned long)maxcount,
3271 (unsigned long)mincount,
3272 (unsigned long)nread ) );
3274 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3276 DEBUG(5,("reply_readbraw finished\n"));
3278 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3280 END_PROFILE(SMBreadbraw);
3281 return;
3284 #undef DBGC_CLASS
3285 #define DBGC_CLASS DBGC_LOCKING
3287 /****************************************************************************
3288 Reply to a lockread (core+ protocol).
3289 ****************************************************************************/
3291 void reply_lockread(struct smb_request *req)
3293 connection_struct *conn = req->conn;
3294 ssize_t nread = -1;
3295 char *data;
3296 SMB_OFF_T startpos;
3297 size_t numtoread;
3298 NTSTATUS status;
3299 files_struct *fsp;
3300 struct byte_range_lock *br_lck = NULL;
3301 char *p = NULL;
3302 struct smbd_server_connection *sconn = req->sconn;
3304 START_PROFILE(SMBlockread);
3306 if (req->wct < 5) {
3307 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3308 END_PROFILE(SMBlockread);
3309 return;
3312 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3314 if (!check_fsp(conn, req, fsp)) {
3315 END_PROFILE(SMBlockread);
3316 return;
3319 if (!CHECK_READ(fsp,req)) {
3320 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3321 END_PROFILE(SMBlockread);
3322 return;
3325 numtoread = SVAL(req->vwv+1, 0);
3326 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3328 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3330 reply_outbuf(req, 5, numtoread + 3);
3332 data = smb_buf(req->outbuf) + 3;
3335 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3336 * protocol request that predates the read/write lock concept.
3337 * Thus instead of asking for a read lock here we need to ask
3338 * for a write lock. JRA.
3339 * Note that the requested lock size is unaffected by max_recv.
3342 br_lck = do_lock(req->sconn->msg_ctx,
3343 fsp,
3344 (uint64_t)req->smbpid,
3345 (uint64_t)numtoread,
3346 (uint64_t)startpos,
3347 WRITE_LOCK,
3348 WINDOWS_LOCK,
3349 False, /* Non-blocking lock. */
3350 &status,
3351 NULL,
3352 NULL);
3353 TALLOC_FREE(br_lck);
3355 if (NT_STATUS_V(status)) {
3356 reply_nterror(req, status);
3357 END_PROFILE(SMBlockread);
3358 return;
3362 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3365 if (numtoread > sconn->smb1.negprot.max_recv) {
3366 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3367 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3368 (unsigned int)numtoread,
3369 (unsigned int)sconn->smb1.negprot.max_recv));
3370 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3372 nread = read_file(fsp,data,startpos,numtoread);
3374 if (nread < 0) {
3375 reply_nterror(req, map_nt_error_from_unix(errno));
3376 END_PROFILE(SMBlockread);
3377 return;
3380 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3382 SSVAL(req->outbuf,smb_vwv0,nread);
3383 SSVAL(req->outbuf,smb_vwv5,nread+3);
3384 p = smb_buf(req->outbuf);
3385 SCVAL(p,0,0); /* pad byte. */
3386 SSVAL(p,1,nread);
3388 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3389 fsp->fnum, (int)numtoread, (int)nread));
3391 END_PROFILE(SMBlockread);
3392 return;
3395 #undef DBGC_CLASS
3396 #define DBGC_CLASS DBGC_ALL
3398 /****************************************************************************
3399 Reply to a read.
3400 ****************************************************************************/
3402 void reply_read(struct smb_request *req)
3404 connection_struct *conn = req->conn;
3405 size_t numtoread;
3406 ssize_t nread = 0;
3407 char *data;
3408 SMB_OFF_T startpos;
3409 int outsize = 0;
3410 files_struct *fsp;
3411 struct lock_struct lock;
3412 struct smbd_server_connection *sconn = req->sconn;
3414 START_PROFILE(SMBread);
3416 if (req->wct < 3) {
3417 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3418 END_PROFILE(SMBread);
3419 return;
3422 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3424 if (!check_fsp(conn, req, fsp)) {
3425 END_PROFILE(SMBread);
3426 return;
3429 if (!CHECK_READ(fsp,req)) {
3430 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3431 END_PROFILE(SMBread);
3432 return;
3435 numtoread = SVAL(req->vwv+1, 0);
3436 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3438 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3441 * The requested read size cannot be greater than max_recv. JRA.
3443 if (numtoread > sconn->smb1.negprot.max_recv) {
3444 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3445 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3446 (unsigned int)numtoread,
3447 (unsigned int)sconn->smb1.negprot.max_recv));
3448 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3451 reply_outbuf(req, 5, numtoread+3);
3453 data = smb_buf(req->outbuf) + 3;
3455 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3456 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3457 &lock);
3459 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3460 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3461 END_PROFILE(SMBread);
3462 return;
3465 if (numtoread > 0)
3466 nread = read_file(fsp,data,startpos,numtoread);
3468 if (nread < 0) {
3469 reply_nterror(req, map_nt_error_from_unix(errno));
3470 goto strict_unlock;
3473 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3475 SSVAL(req->outbuf,smb_vwv0,nread);
3476 SSVAL(req->outbuf,smb_vwv5,nread+3);
3477 SCVAL(smb_buf(req->outbuf),0,1);
3478 SSVAL(smb_buf(req->outbuf),1,nread);
3480 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3481 fsp->fnum, (int)numtoread, (int)nread ) );
3483 strict_unlock:
3484 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3486 END_PROFILE(SMBread);
3487 return;
3490 /****************************************************************************
3491 Setup readX header.
3492 ****************************************************************************/
3494 static int setup_readX_header(struct smb_request *req, char *outbuf,
3495 size_t smb_maxcnt)
3497 int outsize;
3498 char *data;
3500 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3501 data = smb_buf(outbuf);
3503 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3505 SCVAL(outbuf,smb_vwv0,0xFF);
3506 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3507 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3508 SSVAL(outbuf,smb_vwv6,
3509 req_wct_ofs(req)
3510 + 1 /* the wct field */
3511 + 12 * sizeof(uint16_t) /* vwv */
3512 + 2); /* the buflen field */
3513 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3514 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3515 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3516 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3517 return outsize;
3520 /****************************************************************************
3521 Reply to a read and X - possibly using sendfile.
3522 ****************************************************************************/
3524 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3525 files_struct *fsp, SMB_OFF_T startpos,
3526 size_t smb_maxcnt)
3528 ssize_t nread = -1;
3529 struct lock_struct lock;
3530 int saved_errno = 0;
3532 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3533 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3534 &lock);
3536 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3537 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3538 return;
3542 * We can only use sendfile on a non-chained packet
3543 * but we can use on a non-oplocked file. tridge proved this
3544 * on a train in Germany :-). JRA.
3547 if (!req_is_in_chain(req) &&
3548 !req->encrypted && (fsp->base_fsp == NULL) &&
3549 (fsp->wcp == NULL) &&
3550 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3551 uint8 headerbuf[smb_size + 12 * 2];
3552 DATA_BLOB header;
3554 if(fsp_stat(fsp) == -1) {
3555 reply_nterror(req, map_nt_error_from_unix(errno));
3556 goto strict_unlock;
3559 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3560 (startpos > fsp->fsp_name->st.st_ex_size) ||
3561 (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3563 * We already know that we would do a short read, so don't
3564 * try the sendfile() path.
3566 goto nosendfile_read;
3570 * Set up the packet header before send. We
3571 * assume here the sendfile will work (get the
3572 * correct amount of data).
3575 header = data_blob_const(headerbuf, sizeof(headerbuf));
3577 construct_reply_common_req(req, (char *)headerbuf);
3578 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3580 nread = SMB_VFS_SENDFILE(req->sconn->sock, fsp, &header,
3581 startpos, smb_maxcnt);
3582 if (nread == -1) {
3583 /* Returning ENOSYS means no data at all was sent.
3584 Do this as a normal read. */
3585 if (errno == ENOSYS) {
3586 goto normal_read;
3590 * Special hack for broken Linux with no working sendfile. If we
3591 * return EINTR we sent the header but not the rest of the data.
3592 * Fake this up by doing read/write calls.
3595 if (errno == EINTR) {
3596 /* Ensure we don't do this again. */
3597 set_use_sendfile(SNUM(conn), False);
3598 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3599 nread = fake_sendfile(fsp, startpos,
3600 smb_maxcnt);
3601 if (nread == -1) {
3602 DEBUG(0,("send_file_readX: "
3603 "fake_sendfile failed for "
3604 "file %s (%s).\n",
3605 fsp_str_dbg(fsp),
3606 strerror(errno)));
3607 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3609 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3610 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3611 /* No outbuf here means successful sendfile. */
3612 goto strict_unlock;
3615 DEBUG(0,("send_file_readX: sendfile failed for file "
3616 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3617 strerror(errno)));
3618 exit_server_cleanly("send_file_readX sendfile failed");
3619 } else if (nread == 0) {
3621 * Some sendfile implementations return 0 to indicate
3622 * that there was a short read, but nothing was
3623 * actually written to the socket. In this case,
3624 * fallback to the normal read path so the header gets
3625 * the correct byte count.
3627 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3628 "falling back to the normal read: %s\n",
3629 fsp_str_dbg(fsp)));
3630 goto normal_read;
3633 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3634 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3636 /* Deal with possible short send. */
3637 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3638 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3640 /* No outbuf here means successful sendfile. */
3641 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3642 SMB_PERFCOUNT_END(&req->pcd);
3643 goto strict_unlock;
3646 normal_read:
3648 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3649 uint8 headerbuf[smb_size + 2*12];
3651 construct_reply_common_req(req, (char *)headerbuf);
3652 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3654 /* Send out the header. */
3655 if (write_data(req->sconn->sock, (char *)headerbuf,
3656 sizeof(headerbuf)) != sizeof(headerbuf)) {
3658 char addr[INET6_ADDRSTRLEN];
3660 * Try and give an error message saying what
3661 * client failed.
3663 DEBUG(0, ("write_data failed for client %s. "
3664 "Error %s\n",
3665 get_peer_addr(req->sconn->sock, addr,
3666 sizeof(addr)),
3667 strerror(errno)));
3669 DEBUG(0,("send_file_readX: write_data failed for file "
3670 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3671 strerror(errno)));
3672 exit_server_cleanly("send_file_readX sendfile failed");
3674 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3675 if (nread == -1) {
3676 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3677 "file %s (%s).\n", fsp_str_dbg(fsp),
3678 strerror(errno)));
3679 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3681 goto strict_unlock;
3684 nosendfile_read:
3686 reply_outbuf(req, 12, smb_maxcnt);
3688 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3689 saved_errno = errno;
3691 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3693 if (nread < 0) {
3694 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3695 return;
3698 setup_readX_header(req, (char *)req->outbuf, nread);
3700 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3701 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3703 chain_reply(req);
3704 return;
3706 strict_unlock:
3707 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3708 TALLOC_FREE(req->outbuf);
3709 return;
3712 /****************************************************************************
3713 Reply to a read and X.
3714 ****************************************************************************/
3716 void reply_read_and_X(struct smb_request *req)
3718 connection_struct *conn = req->conn;
3719 files_struct *fsp;
3720 SMB_OFF_T startpos;
3721 size_t smb_maxcnt;
3722 bool big_readX = False;
3723 #if 0
3724 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3725 #endif
3727 START_PROFILE(SMBreadX);
3729 if ((req->wct != 10) && (req->wct != 12)) {
3730 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3731 return;
3734 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3735 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3736 smb_maxcnt = SVAL(req->vwv+5, 0);
3738 /* If it's an IPC, pass off the pipe handler. */
3739 if (IS_IPC(conn)) {
3740 reply_pipe_read_and_X(req);
3741 END_PROFILE(SMBreadX);
3742 return;
3745 if (!check_fsp(conn, req, fsp)) {
3746 END_PROFILE(SMBreadX);
3747 return;
3750 if (!CHECK_READ(fsp,req)) {
3751 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3752 END_PROFILE(SMBreadX);
3753 return;
3756 if (global_client_caps & CAP_LARGE_READX) {
3757 size_t upper_size = SVAL(req->vwv+7, 0);
3758 smb_maxcnt |= (upper_size<<16);
3759 if (upper_size > 1) {
3760 /* Can't do this on a chained packet. */
3761 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3762 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3763 END_PROFILE(SMBreadX);
3764 return;
3766 /* We currently don't do this on signed or sealed data. */
3767 if (srv_is_signing_active(req->sconn) || req->encrypted) {
3768 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3769 END_PROFILE(SMBreadX);
3770 return;
3772 /* Is there room in the reply for this data ? */
3773 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3774 reply_nterror(req,
3775 NT_STATUS_INVALID_PARAMETER);
3776 END_PROFILE(SMBreadX);
3777 return;
3779 big_readX = True;
3783 if (req->wct == 12) {
3784 #ifdef LARGE_SMB_OFF_T
3786 * This is a large offset (64 bit) read.
3788 startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3790 #else /* !LARGE_SMB_OFF_T */
3793 * Ensure we haven't been sent a >32 bit offset.
3796 if(IVAL(req->vwv+10, 0) != 0) {
3797 DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3798 "used and we don't support 64 bit offsets.\n",
3799 (unsigned int)IVAL(req->vwv+10, 0) ));
3800 END_PROFILE(SMBreadX);
3801 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3802 return;
3805 #endif /* LARGE_SMB_OFF_T */
3809 if (!big_readX) {
3810 NTSTATUS status = schedule_aio_read_and_X(conn,
3811 req,
3812 fsp,
3813 startpos,
3814 smb_maxcnt);
3815 if (NT_STATUS_IS_OK(status)) {
3816 /* Read scheduled - we're done. */
3817 goto out;
3819 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3820 /* Real error - report to client. */
3821 END_PROFILE(SMBreadX);
3822 reply_nterror(req, status);
3823 return;
3825 /* NT_STATUS_RETRY - fall back to sync read. */
3828 smbd_lock_socket(req->sconn);
3829 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3830 smbd_unlock_socket(req->sconn);
3832 out:
3833 END_PROFILE(SMBreadX);
3834 return;
3837 /****************************************************************************
3838 Error replies to writebraw must have smb_wct == 1. Fix this up.
3839 ****************************************************************************/
3841 void error_to_writebrawerr(struct smb_request *req)
3843 uint8 *old_outbuf = req->outbuf;
3845 reply_outbuf(req, 1, 0);
3847 memcpy(req->outbuf, old_outbuf, smb_size);
3848 TALLOC_FREE(old_outbuf);
3851 /****************************************************************************
3852 Read 4 bytes of a smb packet and return the smb length of the packet.
3853 Store the result in the buffer. This version of the function will
3854 never return a session keepalive (length of zero).
3855 Timeout is in milliseconds.
3856 ****************************************************************************/
3858 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
3859 size_t *len)
3861 uint8_t msgtype = SMBkeepalive;
3863 while (msgtype == SMBkeepalive) {
3864 NTSTATUS status;
3866 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
3867 len);
3868 if (!NT_STATUS_IS_OK(status)) {
3869 char addr[INET6_ADDRSTRLEN];
3870 /* Try and give an error message
3871 * saying what client failed. */
3872 DEBUG(0, ("read_fd_with_timeout failed for "
3873 "client %s read error = %s.\n",
3874 get_peer_addr(fd,addr,sizeof(addr)),
3875 nt_errstr(status)));
3876 return status;
3879 msgtype = CVAL(inbuf, 0);
3882 DEBUG(10,("read_smb_length: got smb length of %lu\n",
3883 (unsigned long)len));
3885 return NT_STATUS_OK;
3888 /****************************************************************************
3889 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3890 ****************************************************************************/
3892 void reply_writebraw(struct smb_request *req)
3894 connection_struct *conn = req->conn;
3895 char *buf = NULL;
3896 ssize_t nwritten=0;
3897 ssize_t total_written=0;
3898 size_t numtowrite=0;
3899 size_t tcount;
3900 SMB_OFF_T startpos;
3901 char *data=NULL;
3902 bool write_through;
3903 files_struct *fsp;
3904 struct lock_struct lock;
3905 NTSTATUS status;
3907 START_PROFILE(SMBwritebraw);
3910 * If we ever reply with an error, it must have the SMB command
3911 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3912 * we're finished.
3914 SCVAL(req->inbuf,smb_com,SMBwritec);
3916 if (srv_is_signing_active(req->sconn)) {
3917 END_PROFILE(SMBwritebraw);
3918 exit_server_cleanly("reply_writebraw: SMB signing is active - "
3919 "raw reads/writes are disallowed.");
3922 if (req->wct < 12) {
3923 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3924 error_to_writebrawerr(req);
3925 END_PROFILE(SMBwritebraw);
3926 return;
3929 if (req->sconn->smb1.echo_handler.trusted_fde) {
3930 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
3931 "'async smb echo handler = yes'\n"));
3932 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3933 error_to_writebrawerr(req);
3934 END_PROFILE(SMBwritebraw);
3935 return;
3938 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3939 if (!check_fsp(conn, req, fsp)) {
3940 error_to_writebrawerr(req);
3941 END_PROFILE(SMBwritebraw);
3942 return;
3945 if (!CHECK_WRITE(fsp)) {
3946 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3947 error_to_writebrawerr(req);
3948 END_PROFILE(SMBwritebraw);
3949 return;
3952 tcount = IVAL(req->vwv+1, 0);
3953 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3954 write_through = BITSETW(req->vwv+7,0);
3956 /* We have to deal with slightly different formats depending
3957 on whether we are using the core+ or lanman1.0 protocol */
3959 if(get_Protocol() <= PROTOCOL_COREPLUS) {
3960 numtowrite = SVAL(smb_buf(req->inbuf),-2);
3961 data = smb_buf(req->inbuf);
3962 } else {
3963 numtowrite = SVAL(req->vwv+10, 0);
3964 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3967 /* Ensure we don't write bytes past the end of this packet. */
3968 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3969 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3970 error_to_writebrawerr(req);
3971 END_PROFILE(SMBwritebraw);
3972 return;
3975 if (!fsp->print_file) {
3976 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3977 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3978 &lock);
3980 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3981 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3982 error_to_writebrawerr(req);
3983 END_PROFILE(SMBwritebraw);
3984 return;
3988 if (numtowrite>0) {
3989 nwritten = write_file(req,fsp,data,startpos,numtowrite);
3992 DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3993 "wrote=%d sync=%d\n",
3994 fsp->fnum, (double)startpos, (int)numtowrite,
3995 (int)nwritten, (int)write_through));
3997 if (nwritten < (ssize_t)numtowrite) {
3998 reply_nterror(req, NT_STATUS_DISK_FULL);
3999 error_to_writebrawerr(req);
4000 goto strict_unlock;
4003 total_written = nwritten;
4005 /* Allocate a buffer of 64k + length. */
4006 buf = TALLOC_ARRAY(NULL, char, 65540);
4007 if (!buf) {
4008 reply_nterror(req, NT_STATUS_NO_MEMORY);
4009 error_to_writebrawerr(req);
4010 goto strict_unlock;
4013 /* Return a SMBwritebraw message to the redirector to tell
4014 * it to send more bytes */
4016 memcpy(buf, req->inbuf, smb_size);
4017 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4018 SCVAL(buf,smb_com,SMBwritebraw);
4019 SSVALS(buf,smb_vwv0,0xFFFF);
4020 show_msg(buf);
4021 if (!srv_send_smb(req->sconn,
4022 buf,
4023 false, 0, /* no signing */
4024 IS_CONN_ENCRYPTED(conn),
4025 &req->pcd)) {
4026 exit_server_cleanly("reply_writebraw: srv_send_smb "
4027 "failed.");
4030 /* Now read the raw data into the buffer and write it */
4031 status = read_smb_length(req->sconn->sock, buf, SMB_SECONDARY_WAIT,
4032 &numtowrite);
4033 if (!NT_STATUS_IS_OK(status)) {
4034 exit_server_cleanly("secondary writebraw failed");
4037 /* Set up outbuf to return the correct size */
4038 reply_outbuf(req, 1, 0);
4040 if (numtowrite != 0) {
4042 if (numtowrite > 0xFFFF) {
4043 DEBUG(0,("reply_writebraw: Oversize secondary write "
4044 "raw requested (%u). Terminating\n",
4045 (unsigned int)numtowrite ));
4046 exit_server_cleanly("secondary writebraw failed");
4049 if (tcount > nwritten+numtowrite) {
4050 DEBUG(3,("reply_writebraw: Client overestimated the "
4051 "write %d %d %d\n",
4052 (int)tcount,(int)nwritten,(int)numtowrite));
4055 status = read_data(req->sconn->sock, buf+4, numtowrite);
4057 if (!NT_STATUS_IS_OK(status)) {
4058 char addr[INET6_ADDRSTRLEN];
4059 /* Try and give an error message
4060 * saying what client failed. */
4061 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4062 "raw read failed (%s) for client %s. "
4063 "Terminating\n", nt_errstr(status),
4064 get_peer_addr(req->sconn->sock, addr,
4065 sizeof(addr))));
4066 exit_server_cleanly("secondary writebraw failed");
4069 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4070 if (nwritten == -1) {
4071 TALLOC_FREE(buf);
4072 reply_nterror(req, map_nt_error_from_unix(errno));
4073 error_to_writebrawerr(req);
4074 goto strict_unlock;
4077 if (nwritten < (ssize_t)numtowrite) {
4078 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4079 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4082 if (nwritten > 0) {
4083 total_written += nwritten;
4087 TALLOC_FREE(buf);
4088 SSVAL(req->outbuf,smb_vwv0,total_written);
4090 status = sync_file(conn, fsp, write_through);
4091 if (!NT_STATUS_IS_OK(status)) {
4092 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4093 fsp_str_dbg(fsp), nt_errstr(status)));
4094 reply_nterror(req, status);
4095 error_to_writebrawerr(req);
4096 goto strict_unlock;
4099 DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
4100 "wrote=%d\n",
4101 fsp->fnum, (double)startpos, (int)numtowrite,
4102 (int)total_written));
4104 if (!fsp->print_file) {
4105 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4108 /* We won't return a status if write through is not selected - this
4109 * follows what WfWg does */
4110 END_PROFILE(SMBwritebraw);
4112 if (!write_through && total_written==tcount) {
4114 #if RABBIT_PELLET_FIX
4116 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4117 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
4118 * JRA.
4120 if (!send_keepalive(req->sconn->sock)) {
4121 exit_server_cleanly("reply_writebraw: send of "
4122 "keepalive failed");
4124 #endif
4125 TALLOC_FREE(req->outbuf);
4127 return;
4129 strict_unlock:
4130 if (!fsp->print_file) {
4131 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4134 END_PROFILE(SMBwritebraw);
4135 return;
4138 #undef DBGC_CLASS
4139 #define DBGC_CLASS DBGC_LOCKING
4141 /****************************************************************************
4142 Reply to a writeunlock (core+).
4143 ****************************************************************************/
4145 void reply_writeunlock(struct smb_request *req)
4147 connection_struct *conn = req->conn;
4148 ssize_t nwritten = -1;
4149 size_t numtowrite;
4150 SMB_OFF_T startpos;
4151 const char *data;
4152 NTSTATUS status = NT_STATUS_OK;
4153 files_struct *fsp;
4154 struct lock_struct lock;
4155 int saved_errno = 0;
4157 START_PROFILE(SMBwriteunlock);
4159 if (req->wct < 5) {
4160 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4161 END_PROFILE(SMBwriteunlock);
4162 return;
4165 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4167 if (!check_fsp(conn, req, fsp)) {
4168 END_PROFILE(SMBwriteunlock);
4169 return;
4172 if (!CHECK_WRITE(fsp)) {
4173 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4174 END_PROFILE(SMBwriteunlock);
4175 return;
4178 numtowrite = SVAL(req->vwv+1, 0);
4179 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4180 data = (const char *)req->buf + 3;
4182 if (!fsp->print_file && numtowrite > 0) {
4183 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4184 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4185 &lock);
4187 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4188 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4189 END_PROFILE(SMBwriteunlock);
4190 return;
4194 /* The special X/Open SMB protocol handling of
4195 zero length writes is *NOT* done for
4196 this call */
4197 if(numtowrite == 0) {
4198 nwritten = 0;
4199 } else {
4200 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4201 saved_errno = errno;
4204 status = sync_file(conn, fsp, False /* write through */);
4205 if (!NT_STATUS_IS_OK(status)) {
4206 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4207 fsp_str_dbg(fsp), nt_errstr(status)));
4208 reply_nterror(req, status);
4209 goto strict_unlock;
4212 if(nwritten < 0) {
4213 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4214 goto strict_unlock;
4217 if((nwritten < numtowrite) && (numtowrite != 0)) {
4218 reply_nterror(req, NT_STATUS_DISK_FULL);
4219 goto strict_unlock;
4222 if (numtowrite && !fsp->print_file) {
4223 status = do_unlock(req->sconn->msg_ctx,
4224 fsp,
4225 (uint64_t)req->smbpid,
4226 (uint64_t)numtowrite,
4227 (uint64_t)startpos,
4228 WINDOWS_LOCK);
4230 if (NT_STATUS_V(status)) {
4231 reply_nterror(req, status);
4232 goto strict_unlock;
4236 reply_outbuf(req, 1, 0);
4238 SSVAL(req->outbuf,smb_vwv0,nwritten);
4240 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4241 fsp->fnum, (int)numtowrite, (int)nwritten));
4243 strict_unlock:
4244 if (numtowrite && !fsp->print_file) {
4245 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4248 END_PROFILE(SMBwriteunlock);
4249 return;
4252 #undef DBGC_CLASS
4253 #define DBGC_CLASS DBGC_ALL
4255 /****************************************************************************
4256 Reply to a write.
4257 ****************************************************************************/
4259 void reply_write(struct smb_request *req)
4261 connection_struct *conn = req->conn;
4262 size_t numtowrite;
4263 ssize_t nwritten = -1;
4264 SMB_OFF_T startpos;
4265 const char *data;
4266 files_struct *fsp;
4267 struct lock_struct lock;
4268 NTSTATUS status;
4269 int saved_errno = 0;
4271 START_PROFILE(SMBwrite);
4273 if (req->wct < 5) {
4274 END_PROFILE(SMBwrite);
4275 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4276 return;
4279 /* If it's an IPC, pass off the pipe handler. */
4280 if (IS_IPC(conn)) {
4281 reply_pipe_write(req);
4282 END_PROFILE(SMBwrite);
4283 return;
4286 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4288 if (!check_fsp(conn, req, fsp)) {
4289 END_PROFILE(SMBwrite);
4290 return;
4293 if (!CHECK_WRITE(fsp)) {
4294 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4295 END_PROFILE(SMBwrite);
4296 return;
4299 numtowrite = SVAL(req->vwv+1, 0);
4300 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4301 data = (const char *)req->buf + 3;
4303 if (!fsp->print_file) {
4304 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4305 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4306 &lock);
4308 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4309 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4310 END_PROFILE(SMBwrite);
4311 return;
4316 * X/Open SMB protocol says that if smb_vwv1 is
4317 * zero then the file size should be extended or
4318 * truncated to the size given in smb_vwv[2-3].
4321 if(numtowrite == 0) {
4323 * This is actually an allocate call, and set EOF. JRA.
4325 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4326 if (nwritten < 0) {
4327 reply_nterror(req, NT_STATUS_DISK_FULL);
4328 goto strict_unlock;
4330 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4331 if (nwritten < 0) {
4332 reply_nterror(req, NT_STATUS_DISK_FULL);
4333 goto strict_unlock;
4335 trigger_write_time_update_immediate(fsp);
4336 } else {
4337 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4340 status = sync_file(conn, fsp, False);
4341 if (!NT_STATUS_IS_OK(status)) {
4342 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4343 fsp_str_dbg(fsp), nt_errstr(status)));
4344 reply_nterror(req, status);
4345 goto strict_unlock;
4348 if(nwritten < 0) {
4349 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4350 goto strict_unlock;
4353 if((nwritten == 0) && (numtowrite != 0)) {
4354 reply_nterror(req, NT_STATUS_DISK_FULL);
4355 goto strict_unlock;
4358 reply_outbuf(req, 1, 0);
4360 SSVAL(req->outbuf,smb_vwv0,nwritten);
4362 if (nwritten < (ssize_t)numtowrite) {
4363 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4364 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4367 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4369 strict_unlock:
4370 if (!fsp->print_file) {
4371 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4374 END_PROFILE(SMBwrite);
4375 return;
4378 /****************************************************************************
4379 Ensure a buffer is a valid writeX for recvfile purposes.
4380 ****************************************************************************/
4382 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4383 (2*14) + /* word count (including bcc) */ \
4384 1 /* pad byte */)
4386 bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
4387 const uint8_t *inbuf)
4389 size_t numtowrite;
4390 connection_struct *conn = NULL;
4391 unsigned int doff = 0;
4392 size_t len = smb_len_large(inbuf);
4394 if (is_encrypted_packet(inbuf)) {
4395 /* Can't do this on encrypted
4396 * connections. */
4397 return false;
4400 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4401 return false;
4404 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4405 CVAL(inbuf,smb_wct) != 14) {
4406 DEBUG(10,("is_valid_writeX_buffer: chained or "
4407 "invalid word length.\n"));
4408 return false;
4411 conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4412 if (conn == NULL) {
4413 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4414 return false;
4416 if (IS_IPC(conn)) {
4417 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4418 return false;
4420 if (IS_PRINT(conn)) {
4421 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4422 return false;
4424 doff = SVAL(inbuf,smb_vwv11);
4426 numtowrite = SVAL(inbuf,smb_vwv10);
4428 if (len > doff && len - doff > 0xFFFF) {
4429 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4432 if (numtowrite == 0) {
4433 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4434 return false;
4437 /* Ensure the sizes match up. */
4438 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4439 /* no pad byte...old smbclient :-( */
4440 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4441 (unsigned int)doff,
4442 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4443 return false;
4446 if (len - doff != numtowrite) {
4447 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4448 "len = %u, doff = %u, numtowrite = %u\n",
4449 (unsigned int)len,
4450 (unsigned int)doff,
4451 (unsigned int)numtowrite ));
4452 return false;
4455 DEBUG(10,("is_valid_writeX_buffer: true "
4456 "len = %u, doff = %u, numtowrite = %u\n",
4457 (unsigned int)len,
4458 (unsigned int)doff,
4459 (unsigned int)numtowrite ));
4461 return true;
4464 /****************************************************************************
4465 Reply to a write and X.
4466 ****************************************************************************/
4468 void reply_write_and_X(struct smb_request *req)
4470 connection_struct *conn = req->conn;
4471 files_struct *fsp;
4472 struct lock_struct lock;
4473 SMB_OFF_T startpos;
4474 size_t numtowrite;
4475 bool write_through;
4476 ssize_t nwritten;
4477 unsigned int smb_doff;
4478 unsigned int smblen;
4479 char *data;
4480 NTSTATUS status;
4481 int saved_errno = 0;
4483 START_PROFILE(SMBwriteX);
4485 if ((req->wct != 12) && (req->wct != 14)) {
4486 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4487 END_PROFILE(SMBwriteX);
4488 return;
4491 numtowrite = SVAL(req->vwv+10, 0);
4492 smb_doff = SVAL(req->vwv+11, 0);
4493 smblen = smb_len(req->inbuf);
4495 if (req->unread_bytes > 0xFFFF ||
4496 (smblen > smb_doff &&
4497 smblen - smb_doff > 0xFFFF)) {
4498 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4501 if (req->unread_bytes) {
4502 /* Can't do a recvfile write on IPC$ */
4503 if (IS_IPC(conn)) {
4504 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4505 END_PROFILE(SMBwriteX);
4506 return;
4508 if (numtowrite != req->unread_bytes) {
4509 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4510 END_PROFILE(SMBwriteX);
4511 return;
4513 } else {
4514 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4515 smb_doff + numtowrite > smblen) {
4516 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4517 END_PROFILE(SMBwriteX);
4518 return;
4522 /* If it's an IPC, pass off the pipe handler. */
4523 if (IS_IPC(conn)) {
4524 if (req->unread_bytes) {
4525 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4526 END_PROFILE(SMBwriteX);
4527 return;
4529 reply_pipe_write_and_X(req);
4530 END_PROFILE(SMBwriteX);
4531 return;
4534 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4535 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4536 write_through = BITSETW(req->vwv+7,0);
4538 if (!check_fsp(conn, req, fsp)) {
4539 END_PROFILE(SMBwriteX);
4540 return;
4543 if (!CHECK_WRITE(fsp)) {
4544 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4545 END_PROFILE(SMBwriteX);
4546 return;
4549 data = smb_base(req->inbuf) + smb_doff;
4551 if(req->wct == 14) {
4552 #ifdef LARGE_SMB_OFF_T
4554 * This is a large offset (64 bit) write.
4556 startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4558 #else /* !LARGE_SMB_OFF_T */
4561 * Ensure we haven't been sent a >32 bit offset.
4564 if(IVAL(req->vwv+12, 0) != 0) {
4565 DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4566 "used and we don't support 64 bit offsets.\n",
4567 (unsigned int)IVAL(req->vwv+12, 0) ));
4568 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4569 END_PROFILE(SMBwriteX);
4570 return;
4573 #endif /* LARGE_SMB_OFF_T */
4576 /* X/Open SMB protocol says that, unlike SMBwrite
4577 if the length is zero then NO truncation is
4578 done, just a write of zero. To truncate a file,
4579 use SMBwrite. */
4581 if(numtowrite == 0) {
4582 nwritten = 0;
4583 } else {
4584 if (req->unread_bytes == 0) {
4585 status = schedule_aio_write_and_X(conn,
4586 req,
4587 fsp,
4588 data,
4589 startpos,
4590 numtowrite);
4592 if (NT_STATUS_IS_OK(status)) {
4593 /* write scheduled - we're done. */
4594 goto out;
4596 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4597 /* Real error - report to client. */
4598 reply_nterror(req, status);
4599 goto out;
4601 /* NT_STATUS_RETRY - fall through to sync write. */
4604 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4605 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4606 &lock);
4608 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4609 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4610 goto out;
4613 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4614 saved_errno = errno;
4616 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4619 if(nwritten < 0) {
4620 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4621 goto out;
4624 if((nwritten == 0) && (numtowrite != 0)) {
4625 reply_nterror(req, NT_STATUS_DISK_FULL);
4626 goto out;
4629 reply_outbuf(req, 6, 0);
4630 SSVAL(req->outbuf,smb_vwv2,nwritten);
4631 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4633 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4634 fsp->fnum, (int)numtowrite, (int)nwritten));
4636 status = sync_file(conn, fsp, write_through);
4637 if (!NT_STATUS_IS_OK(status)) {
4638 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4639 fsp_str_dbg(fsp), nt_errstr(status)));
4640 reply_nterror(req, status);
4641 goto out;
4644 END_PROFILE(SMBwriteX);
4645 chain_reply(req);
4646 return;
4648 out:
4649 END_PROFILE(SMBwriteX);
4650 return;
4653 /****************************************************************************
4654 Reply to a lseek.
4655 ****************************************************************************/
4657 void reply_lseek(struct smb_request *req)
4659 connection_struct *conn = req->conn;
4660 SMB_OFF_T startpos;
4661 SMB_OFF_T res= -1;
4662 int mode,umode;
4663 files_struct *fsp;
4665 START_PROFILE(SMBlseek);
4667 if (req->wct < 4) {
4668 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4669 END_PROFILE(SMBlseek);
4670 return;
4673 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4675 if (!check_fsp(conn, req, fsp)) {
4676 return;
4679 flush_write_cache(fsp, SEEK_FLUSH);
4681 mode = SVAL(req->vwv+1, 0) & 3;
4682 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4683 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4685 switch (mode) {
4686 case 0:
4687 umode = SEEK_SET;
4688 res = startpos;
4689 break;
4690 case 1:
4691 umode = SEEK_CUR;
4692 res = fsp->fh->pos + startpos;
4693 break;
4694 case 2:
4695 umode = SEEK_END;
4696 break;
4697 default:
4698 umode = SEEK_SET;
4699 res = startpos;
4700 break;
4703 if (umode == SEEK_END) {
4704 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4705 if(errno == EINVAL) {
4706 SMB_OFF_T current_pos = startpos;
4708 if(fsp_stat(fsp) == -1) {
4709 reply_nterror(req,
4710 map_nt_error_from_unix(errno));
4711 END_PROFILE(SMBlseek);
4712 return;
4715 current_pos += fsp->fsp_name->st.st_ex_size;
4716 if(current_pos < 0)
4717 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4721 if(res == -1) {
4722 reply_nterror(req, map_nt_error_from_unix(errno));
4723 END_PROFILE(SMBlseek);
4724 return;
4728 fsp->fh->pos = res;
4730 reply_outbuf(req, 2, 0);
4731 SIVAL(req->outbuf,smb_vwv0,res);
4733 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4734 fsp->fnum, (double)startpos, (double)res, mode));
4736 END_PROFILE(SMBlseek);
4737 return;
4740 /****************************************************************************
4741 Reply to a flush.
4742 ****************************************************************************/
4744 void reply_flush(struct smb_request *req)
4746 connection_struct *conn = req->conn;
4747 uint16 fnum;
4748 files_struct *fsp;
4750 START_PROFILE(SMBflush);
4752 if (req->wct < 1) {
4753 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4754 return;
4757 fnum = SVAL(req->vwv+0, 0);
4758 fsp = file_fsp(req, fnum);
4760 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4761 return;
4764 if (!fsp) {
4765 file_sync_all(conn);
4766 } else {
4767 NTSTATUS status = sync_file(conn, fsp, True);
4768 if (!NT_STATUS_IS_OK(status)) {
4769 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4770 fsp_str_dbg(fsp), nt_errstr(status)));
4771 reply_nterror(req, status);
4772 END_PROFILE(SMBflush);
4773 return;
4777 reply_outbuf(req, 0, 0);
4779 DEBUG(3,("flush\n"));
4780 END_PROFILE(SMBflush);
4781 return;
4784 /****************************************************************************
4785 Reply to a exit.
4786 conn POINTER CAN BE NULL HERE !
4787 ****************************************************************************/
4789 void reply_exit(struct smb_request *req)
4791 START_PROFILE(SMBexit);
4793 file_close_pid(req->sconn, req->smbpid, req->vuid);
4795 reply_outbuf(req, 0, 0);
4797 DEBUG(3,("exit\n"));
4799 END_PROFILE(SMBexit);
4800 return;
4803 /****************************************************************************
4804 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4805 ****************************************************************************/
4807 void reply_close(struct smb_request *req)
4809 connection_struct *conn = req->conn;
4810 NTSTATUS status = NT_STATUS_OK;
4811 files_struct *fsp = NULL;
4812 START_PROFILE(SMBclose);
4814 if (req->wct < 3) {
4815 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4816 END_PROFILE(SMBclose);
4817 return;
4820 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4823 * We can only use check_fsp if we know it's not a directory.
4826 if (!check_fsp_open(conn, req, fsp)) {
4827 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4828 END_PROFILE(SMBclose);
4829 return;
4832 if(fsp->is_directory) {
4834 * Special case - close NT SMB directory handle.
4836 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4837 status = close_file(req, fsp, NORMAL_CLOSE);
4838 } else {
4839 time_t t;
4841 * Close ordinary file.
4844 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4845 fsp->fh->fd, fsp->fnum,
4846 conn->num_files_open));
4849 * Take care of any time sent in the close.
4852 t = srv_make_unix_date3(req->vwv+1);
4853 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4856 * close_file() returns the unix errno if an error
4857 * was detected on close - normally this is due to
4858 * a disk full error. If not then it was probably an I/O error.
4861 status = close_file(req, fsp, NORMAL_CLOSE);
4864 if (!NT_STATUS_IS_OK(status)) {
4865 reply_nterror(req, status);
4866 END_PROFILE(SMBclose);
4867 return;
4870 reply_outbuf(req, 0, 0);
4871 END_PROFILE(SMBclose);
4872 return;
4875 /****************************************************************************
4876 Reply to a writeclose (Core+ protocol).
4877 ****************************************************************************/
4879 void reply_writeclose(struct smb_request *req)
4881 connection_struct *conn = req->conn;
4882 size_t numtowrite;
4883 ssize_t nwritten = -1;
4884 NTSTATUS close_status = NT_STATUS_OK;
4885 SMB_OFF_T startpos;
4886 const char *data;
4887 struct timespec mtime;
4888 files_struct *fsp;
4889 struct lock_struct lock;
4891 START_PROFILE(SMBwriteclose);
4893 if (req->wct < 6) {
4894 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4895 END_PROFILE(SMBwriteclose);
4896 return;
4899 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4901 if (!check_fsp(conn, req, fsp)) {
4902 END_PROFILE(SMBwriteclose);
4903 return;
4905 if (!CHECK_WRITE(fsp)) {
4906 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4907 END_PROFILE(SMBwriteclose);
4908 return;
4911 numtowrite = SVAL(req->vwv+1, 0);
4912 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4913 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4914 data = (const char *)req->buf + 1;
4916 if (!fsp->print_file) {
4917 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4918 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4919 &lock);
4921 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4922 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4923 END_PROFILE(SMBwriteclose);
4924 return;
4928 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4930 set_close_write_time(fsp, mtime);
4933 * More insanity. W2K only closes the file if writelen > 0.
4934 * JRA.
4937 if (numtowrite) {
4938 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4939 "file %s\n", fsp_str_dbg(fsp)));
4940 close_status = close_file(req, fsp, NORMAL_CLOSE);
4943 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4944 fsp->fnum, (int)numtowrite, (int)nwritten,
4945 conn->num_files_open));
4947 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4948 reply_nterror(req, NT_STATUS_DISK_FULL);
4949 goto strict_unlock;
4952 if(!NT_STATUS_IS_OK(close_status)) {
4953 reply_nterror(req, close_status);
4954 goto strict_unlock;
4957 reply_outbuf(req, 1, 0);
4959 SSVAL(req->outbuf,smb_vwv0,nwritten);
4961 strict_unlock:
4962 if (numtowrite && !fsp->print_file) {
4963 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4966 END_PROFILE(SMBwriteclose);
4967 return;
4970 #undef DBGC_CLASS
4971 #define DBGC_CLASS DBGC_LOCKING
4973 /****************************************************************************
4974 Reply to a lock.
4975 ****************************************************************************/
4977 void reply_lock(struct smb_request *req)
4979 connection_struct *conn = req->conn;
4980 uint64_t count,offset;
4981 NTSTATUS status;
4982 files_struct *fsp;
4983 struct byte_range_lock *br_lck = NULL;
4985 START_PROFILE(SMBlock);
4987 if (req->wct < 5) {
4988 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4989 END_PROFILE(SMBlock);
4990 return;
4993 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4995 if (!check_fsp(conn, req, fsp)) {
4996 END_PROFILE(SMBlock);
4997 return;
5000 count = (uint64_t)IVAL(req->vwv+1, 0);
5001 offset = (uint64_t)IVAL(req->vwv+3, 0);
5003 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5004 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
5006 br_lck = do_lock(req->sconn->msg_ctx,
5007 fsp,
5008 (uint64_t)req->smbpid,
5009 count,
5010 offset,
5011 WRITE_LOCK,
5012 WINDOWS_LOCK,
5013 False, /* Non-blocking lock. */
5014 &status,
5015 NULL,
5016 NULL);
5018 TALLOC_FREE(br_lck);
5020 if (NT_STATUS_V(status)) {
5021 reply_nterror(req, status);
5022 END_PROFILE(SMBlock);
5023 return;
5026 reply_outbuf(req, 0, 0);
5028 END_PROFILE(SMBlock);
5029 return;
5032 /****************************************************************************
5033 Reply to a unlock.
5034 ****************************************************************************/
5036 void reply_unlock(struct smb_request *req)
5038 connection_struct *conn = req->conn;
5039 uint64_t count,offset;
5040 NTSTATUS status;
5041 files_struct *fsp;
5043 START_PROFILE(SMBunlock);
5045 if (req->wct < 5) {
5046 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5047 END_PROFILE(SMBunlock);
5048 return;
5051 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5053 if (!check_fsp(conn, req, fsp)) {
5054 END_PROFILE(SMBunlock);
5055 return;
5058 count = (uint64_t)IVAL(req->vwv+1, 0);
5059 offset = (uint64_t)IVAL(req->vwv+3, 0);
5061 status = do_unlock(req->sconn->msg_ctx,
5062 fsp,
5063 (uint64_t)req->smbpid,
5064 count,
5065 offset,
5066 WINDOWS_LOCK);
5068 if (NT_STATUS_V(status)) {
5069 reply_nterror(req, status);
5070 END_PROFILE(SMBunlock);
5071 return;
5074 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5075 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
5077 reply_outbuf(req, 0, 0);
5079 END_PROFILE(SMBunlock);
5080 return;
5083 #undef DBGC_CLASS
5084 #define DBGC_CLASS DBGC_ALL
5086 /****************************************************************************
5087 Reply to a tdis.
5088 conn POINTER CAN BE NULL HERE !
5089 ****************************************************************************/
5091 void reply_tdis(struct smb_request *req)
5093 connection_struct *conn = req->conn;
5094 START_PROFILE(SMBtdis);
5096 if (!conn) {
5097 DEBUG(4,("Invalid connection in tdis\n"));
5098 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
5099 END_PROFILE(SMBtdis);
5100 return;
5103 conn->used = False;
5105 close_cnum(conn,req->vuid);
5106 req->conn = NULL;
5108 reply_outbuf(req, 0, 0);
5109 END_PROFILE(SMBtdis);
5110 return;
5113 /****************************************************************************
5114 Reply to a echo.
5115 conn POINTER CAN BE NULL HERE !
5116 ****************************************************************************/
5118 void reply_echo(struct smb_request *req)
5120 connection_struct *conn = req->conn;
5121 struct smb_perfcount_data local_pcd;
5122 struct smb_perfcount_data *cur_pcd;
5123 int smb_reverb;
5124 int seq_num;
5126 START_PROFILE(SMBecho);
5128 smb_init_perfcount_data(&local_pcd);
5130 if (req->wct < 1) {
5131 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5132 END_PROFILE(SMBecho);
5133 return;
5136 smb_reverb = SVAL(req->vwv+0, 0);
5138 reply_outbuf(req, 1, req->buflen);
5140 /* copy any incoming data back out */
5141 if (req->buflen > 0) {
5142 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5145 if (smb_reverb > 100) {
5146 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5147 smb_reverb = 100;
5150 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5152 /* this makes sure we catch the request pcd */
5153 if (seq_num == smb_reverb) {
5154 cur_pcd = &req->pcd;
5155 } else {
5156 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5157 cur_pcd = &local_pcd;
5160 SSVAL(req->outbuf,smb_vwv0,seq_num);
5162 show_msg((char *)req->outbuf);
5163 if (!srv_send_smb(req->sconn,
5164 (char *)req->outbuf,
5165 true, req->seqnum+1,
5166 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5167 cur_pcd))
5168 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5171 DEBUG(3,("echo %d times\n", smb_reverb));
5173 TALLOC_FREE(req->outbuf);
5175 END_PROFILE(SMBecho);
5176 return;
5179 /****************************************************************************
5180 Reply to a printopen.
5181 ****************************************************************************/
5183 void reply_printopen(struct smb_request *req)
5185 connection_struct *conn = req->conn;
5186 files_struct *fsp;
5187 NTSTATUS status;
5189 START_PROFILE(SMBsplopen);
5191 if (req->wct < 2) {
5192 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5193 END_PROFILE(SMBsplopen);
5194 return;
5197 if (!CAN_PRINT(conn)) {
5198 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5199 END_PROFILE(SMBsplopen);
5200 return;
5203 status = file_new(req, conn, &fsp);
5204 if(!NT_STATUS_IS_OK(status)) {
5205 reply_nterror(req, status);
5206 END_PROFILE(SMBsplopen);
5207 return;
5210 /* Open for exclusive use, write only. */
5211 status = print_spool_open(fsp, NULL, req->vuid);
5213 if (!NT_STATUS_IS_OK(status)) {
5214 file_free(req, fsp);
5215 reply_nterror(req, status);
5216 END_PROFILE(SMBsplopen);
5217 return;
5220 reply_outbuf(req, 1, 0);
5221 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5223 DEBUG(3,("openprint fd=%d fnum=%d\n",
5224 fsp->fh->fd, fsp->fnum));
5226 END_PROFILE(SMBsplopen);
5227 return;
5230 /****************************************************************************
5231 Reply to a printclose.
5232 ****************************************************************************/
5234 void reply_printclose(struct smb_request *req)
5236 connection_struct *conn = req->conn;
5237 files_struct *fsp;
5238 NTSTATUS status;
5240 START_PROFILE(SMBsplclose);
5242 if (req->wct < 1) {
5243 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5244 END_PROFILE(SMBsplclose);
5245 return;
5248 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5250 if (!check_fsp(conn, req, fsp)) {
5251 END_PROFILE(SMBsplclose);
5252 return;
5255 if (!CAN_PRINT(conn)) {
5256 reply_force_doserror(req, ERRSRV, ERRerror);
5257 END_PROFILE(SMBsplclose);
5258 return;
5261 DEBUG(3,("printclose fd=%d fnum=%d\n",
5262 fsp->fh->fd,fsp->fnum));
5264 status = close_file(req, fsp, NORMAL_CLOSE);
5266 if(!NT_STATUS_IS_OK(status)) {
5267 reply_nterror(req, status);
5268 END_PROFILE(SMBsplclose);
5269 return;
5272 reply_outbuf(req, 0, 0);
5274 END_PROFILE(SMBsplclose);
5275 return;
5278 /****************************************************************************
5279 Reply to a printqueue.
5280 ****************************************************************************/
5282 void reply_printqueue(struct smb_request *req)
5284 connection_struct *conn = req->conn;
5285 int max_count;
5286 int start_index;
5288 START_PROFILE(SMBsplretq);
5290 if (req->wct < 2) {
5291 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5292 END_PROFILE(SMBsplretq);
5293 return;
5296 max_count = SVAL(req->vwv+0, 0);
5297 start_index = SVAL(req->vwv+1, 0);
5299 /* we used to allow the client to get the cnum wrong, but that
5300 is really quite gross and only worked when there was only
5301 one printer - I think we should now only accept it if they
5302 get it right (tridge) */
5303 if (!CAN_PRINT(conn)) {
5304 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5305 END_PROFILE(SMBsplretq);
5306 return;
5309 reply_outbuf(req, 2, 3);
5310 SSVAL(req->outbuf,smb_vwv0,0);
5311 SSVAL(req->outbuf,smb_vwv1,0);
5312 SCVAL(smb_buf(req->outbuf),0,1);
5313 SSVAL(smb_buf(req->outbuf),1,0);
5315 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5316 start_index, max_count));
5319 TALLOC_CTX *mem_ctx = talloc_tos();
5320 NTSTATUS status;
5321 WERROR werr;
5322 const char *sharename = lp_servicename(SNUM(conn));
5323 struct rpc_pipe_client *cli = NULL;
5324 struct dcerpc_binding_handle *b = NULL;
5325 struct policy_handle handle;
5326 struct spoolss_DevmodeContainer devmode_ctr;
5327 union spoolss_JobInfo *info;
5328 uint32_t count;
5329 uint32_t num_to_get;
5330 uint32_t first;
5331 uint32_t i;
5333 ZERO_STRUCT(handle);
5335 status = rpc_pipe_open_interface(conn,
5336 &ndr_table_spoolss.syntax_id,
5337 conn->session_info,
5338 &conn->sconn->client_id,
5339 conn->sconn->msg_ctx,
5340 &cli);
5341 if (!NT_STATUS_IS_OK(status)) {
5342 DEBUG(0, ("reply_printqueue: "
5343 "could not connect to spoolss: %s\n",
5344 nt_errstr(status)));
5345 reply_nterror(req, status);
5346 goto out;
5348 b = cli->binding_handle;
5350 ZERO_STRUCT(devmode_ctr);
5352 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5353 sharename,
5354 NULL, devmode_ctr,
5355 SEC_FLAG_MAXIMUM_ALLOWED,
5356 &handle,
5357 &werr);
5358 if (!NT_STATUS_IS_OK(status)) {
5359 reply_nterror(req, status);
5360 goto out;
5362 if (!W_ERROR_IS_OK(werr)) {
5363 reply_nterror(req, werror_to_ntstatus(werr));
5364 goto out;
5367 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5368 &handle,
5369 0, /* firstjob */
5370 0xff, /* numjobs */
5371 2, /* level */
5372 0, /* offered */
5373 &count,
5374 &info);
5375 if (!W_ERROR_IS_OK(werr)) {
5376 reply_nterror(req, werror_to_ntstatus(werr));
5377 goto out;
5380 if (max_count > 0) {
5381 first = start_index;
5382 } else {
5383 first = start_index + max_count + 1;
5386 if (first >= count) {
5387 num_to_get = first;
5388 } else {
5389 num_to_get = first + MIN(ABS(max_count), count - first);
5392 for (i = first; i < num_to_get; i++) {
5393 char blob[28];
5394 char *p = blob;
5395 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5396 int qstatus;
5397 uint16_t qrapjobid = pjobid_to_rap(sharename,
5398 info[i].info2.job_id);
5400 if (info[i].info2.status == JOB_STATUS_PRINTING) {
5401 qstatus = 2;
5402 } else {
5403 qstatus = 3;
5406 srv_put_dos_date2(p, 0, qtime);
5407 SCVAL(p, 4, qstatus);
5408 SSVAL(p, 5, qrapjobid);
5409 SIVAL(p, 7, info[i].info2.size);
5410 SCVAL(p, 11, 0);
5411 srvstr_push(blob, req->flags2, p+12,
5412 info[i].info2.notify_name, 16, STR_ASCII);
5414 if (message_push_blob(
5415 &req->outbuf,
5416 data_blob_const(
5417 blob, sizeof(blob))) == -1) {
5418 reply_nterror(req, NT_STATUS_NO_MEMORY);
5419 goto out;
5423 if (count > 0) {
5424 SSVAL(req->outbuf,smb_vwv0,count);
5425 SSVAL(req->outbuf,smb_vwv1,
5426 (max_count>0?first+count:first-1));
5427 SCVAL(smb_buf(req->outbuf),0,1);
5428 SSVAL(smb_buf(req->outbuf),1,28*count);
5432 DEBUG(3, ("%u entries returned in queue\n",
5433 (unsigned)count));
5435 out:
5436 if (b && is_valid_policy_hnd(&handle)) {
5437 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5442 END_PROFILE(SMBsplretq);
5443 return;
5446 /****************************************************************************
5447 Reply to a printwrite.
5448 ****************************************************************************/
5450 void reply_printwrite(struct smb_request *req)
5452 connection_struct *conn = req->conn;
5453 int numtowrite;
5454 const char *data;
5455 files_struct *fsp;
5457 START_PROFILE(SMBsplwr);
5459 if (req->wct < 1) {
5460 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5461 END_PROFILE(SMBsplwr);
5462 return;
5465 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5467 if (!check_fsp(conn, req, fsp)) {
5468 END_PROFILE(SMBsplwr);
5469 return;
5472 if (!fsp->print_file) {
5473 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5474 END_PROFILE(SMBsplwr);
5475 return;
5478 if (!CHECK_WRITE(fsp)) {
5479 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5480 END_PROFILE(SMBsplwr);
5481 return;
5484 numtowrite = SVAL(req->buf, 1);
5486 if (req->buflen < numtowrite + 3) {
5487 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5488 END_PROFILE(SMBsplwr);
5489 return;
5492 data = (const char *)req->buf + 3;
5494 if (write_file(req,fsp,data,(SMB_OFF_T)-1,numtowrite) != numtowrite) {
5495 reply_nterror(req, map_nt_error_from_unix(errno));
5496 END_PROFILE(SMBsplwr);
5497 return;
5500 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5502 END_PROFILE(SMBsplwr);
5503 return;
5506 /****************************************************************************
5507 Reply to a mkdir.
5508 ****************************************************************************/
5510 void reply_mkdir(struct smb_request *req)
5512 connection_struct *conn = req->conn;
5513 struct smb_filename *smb_dname = NULL;
5514 char *directory = NULL;
5515 NTSTATUS status;
5516 TALLOC_CTX *ctx = talloc_tos();
5518 START_PROFILE(SMBmkdir);
5520 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5521 STR_TERMINATE, &status);
5522 if (!NT_STATUS_IS_OK(status)) {
5523 reply_nterror(req, status);
5524 goto out;
5527 status = filename_convert(ctx, conn,
5528 req->flags2 & FLAGS2_DFS_PATHNAMES,
5529 directory,
5531 NULL,
5532 &smb_dname);
5533 if (!NT_STATUS_IS_OK(status)) {
5534 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5535 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5536 ERRSRV, ERRbadpath);
5537 goto out;
5539 reply_nterror(req, status);
5540 goto out;
5543 status = create_directory(conn, req, smb_dname);
5545 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5547 if (!NT_STATUS_IS_OK(status)) {
5549 if (!use_nt_status()
5550 && NT_STATUS_EQUAL(status,
5551 NT_STATUS_OBJECT_NAME_COLLISION)) {
5553 * Yes, in the DOS error code case we get a
5554 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5555 * samba4 torture test.
5557 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5560 reply_nterror(req, status);
5561 goto out;
5564 reply_outbuf(req, 0, 0);
5566 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5567 out:
5568 TALLOC_FREE(smb_dname);
5569 END_PROFILE(SMBmkdir);
5570 return;
5573 /****************************************************************************
5574 Reply to a rmdir.
5575 ****************************************************************************/
5577 void reply_rmdir(struct smb_request *req)
5579 connection_struct *conn = req->conn;
5580 struct smb_filename *smb_dname = NULL;
5581 char *directory = NULL;
5582 NTSTATUS status;
5583 TALLOC_CTX *ctx = talloc_tos();
5584 files_struct *fsp = NULL;
5585 int info = 0;
5586 struct smbd_server_connection *sconn = req->sconn;
5588 START_PROFILE(SMBrmdir);
5590 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5591 STR_TERMINATE, &status);
5592 if (!NT_STATUS_IS_OK(status)) {
5593 reply_nterror(req, status);
5594 goto out;
5597 status = filename_convert(ctx, conn,
5598 req->flags2 & FLAGS2_DFS_PATHNAMES,
5599 directory,
5601 NULL,
5602 &smb_dname);
5603 if (!NT_STATUS_IS_OK(status)) {
5604 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5605 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5606 ERRSRV, ERRbadpath);
5607 goto out;
5609 reply_nterror(req, status);
5610 goto out;
5613 if (is_ntfs_stream_smb_fname(smb_dname)) {
5614 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5615 goto out;
5618 status = SMB_VFS_CREATE_FILE(
5619 conn, /* conn */
5620 req, /* req */
5621 0, /* root_dir_fid */
5622 smb_dname, /* fname */
5623 DELETE_ACCESS, /* access_mask */
5624 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5625 FILE_SHARE_DELETE),
5626 FILE_OPEN, /* create_disposition*/
5627 FILE_DIRECTORY_FILE, /* create_options */
5628 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
5629 0, /* oplock_request */
5630 0, /* allocation_size */
5631 0, /* private_flags */
5632 NULL, /* sd */
5633 NULL, /* ea_list */
5634 &fsp, /* result */
5635 &info); /* pinfo */
5637 if (!NT_STATUS_IS_OK(status)) {
5638 if (open_was_deferred(req->mid)) {
5639 /* We have re-scheduled this call. */
5640 goto out;
5642 reply_nterror(req, status);
5643 goto out;
5646 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5647 if (!NT_STATUS_IS_OK(status)) {
5648 close_file(req, fsp, ERROR_CLOSE);
5649 reply_nterror(req, status);
5650 goto out;
5653 if (!set_delete_on_close(fsp, true,
5654 conn->session_info->security_token,
5655 &conn->session_info->utok)) {
5656 close_file(req, fsp, ERROR_CLOSE);
5657 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5658 goto out;
5661 status = close_file(req, fsp, NORMAL_CLOSE);
5662 if (!NT_STATUS_IS_OK(status)) {
5663 reply_nterror(req, status);
5664 } else {
5665 reply_outbuf(req, 0, 0);
5668 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5670 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5671 out:
5672 TALLOC_FREE(smb_dname);
5673 END_PROFILE(SMBrmdir);
5674 return;
5677 /*******************************************************************
5678 Resolve wildcards in a filename rename.
5679 ********************************************************************/
5681 static bool resolve_wildcards(TALLOC_CTX *ctx,
5682 const char *name1,
5683 const char *name2,
5684 char **pp_newname)
5686 char *name2_copy = NULL;
5687 char *root1 = NULL;
5688 char *root2 = NULL;
5689 char *ext1 = NULL;
5690 char *ext2 = NULL;
5691 char *p,*p2, *pname1, *pname2;
5693 name2_copy = talloc_strdup(ctx, name2);
5694 if (!name2_copy) {
5695 return False;
5698 pname1 = strrchr_m(name1,'/');
5699 pname2 = strrchr_m(name2_copy,'/');
5701 if (!pname1 || !pname2) {
5702 return False;
5705 /* Truncate the copy of name2 at the last '/' */
5706 *pname2 = '\0';
5708 /* Now go past the '/' */
5709 pname1++;
5710 pname2++;
5712 root1 = talloc_strdup(ctx, pname1);
5713 root2 = talloc_strdup(ctx, pname2);
5715 if (!root1 || !root2) {
5716 return False;
5719 p = strrchr_m(root1,'.');
5720 if (p) {
5721 *p = 0;
5722 ext1 = talloc_strdup(ctx, p+1);
5723 } else {
5724 ext1 = talloc_strdup(ctx, "");
5726 p = strrchr_m(root2,'.');
5727 if (p) {
5728 *p = 0;
5729 ext2 = talloc_strdup(ctx, p+1);
5730 } else {
5731 ext2 = talloc_strdup(ctx, "");
5734 if (!ext1 || !ext2) {
5735 return False;
5738 p = root1;
5739 p2 = root2;
5740 while (*p2) {
5741 if (*p2 == '?') {
5742 /* Hmmm. Should this be mb-aware ? */
5743 *p2 = *p;
5744 p2++;
5745 } else if (*p2 == '*') {
5746 *p2 = '\0';
5747 root2 = talloc_asprintf(ctx, "%s%s",
5748 root2,
5750 if (!root2) {
5751 return False;
5753 break;
5754 } else {
5755 p2++;
5757 if (*p) {
5758 p++;
5762 p = ext1;
5763 p2 = ext2;
5764 while (*p2) {
5765 if (*p2 == '?') {
5766 /* Hmmm. Should this be mb-aware ? */
5767 *p2 = *p;
5768 p2++;
5769 } else if (*p2 == '*') {
5770 *p2 = '\0';
5771 ext2 = talloc_asprintf(ctx, "%s%s",
5772 ext2,
5774 if (!ext2) {
5775 return False;
5777 break;
5778 } else {
5779 p2++;
5781 if (*p) {
5782 p++;
5786 if (*ext2) {
5787 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5788 name2_copy,
5789 root2,
5790 ext2);
5791 } else {
5792 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5793 name2_copy,
5794 root2);
5797 if (!*pp_newname) {
5798 return False;
5801 return True;
5804 /****************************************************************************
5805 Ensure open files have their names updated. Updated to notify other smbd's
5806 asynchronously.
5807 ****************************************************************************/
5809 static void rename_open_files(connection_struct *conn,
5810 struct share_mode_lock *lck,
5811 uint32_t orig_name_hash,
5812 const struct smb_filename *smb_fname_dst)
5814 files_struct *fsp;
5815 bool did_rename = False;
5816 NTSTATUS status;
5817 uint32_t new_name_hash;
5819 for(fsp = file_find_di_first(conn->sconn, lck->id); fsp;
5820 fsp = file_find_di_next(fsp)) {
5821 /* fsp_name is a relative path under the fsp. To change this for other
5822 sharepaths we need to manipulate relative paths. */
5823 /* TODO - create the absolute path and manipulate the newname
5824 relative to the sharepath. */
5825 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5826 continue;
5828 if (fsp->name_hash != orig_name_hash) {
5829 continue;
5831 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5832 "(file_id %s) from %s -> %s\n", fsp->fnum,
5833 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5834 smb_fname_str_dbg(smb_fname_dst)));
5836 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5837 if (NT_STATUS_IS_OK(status)) {
5838 did_rename = True;
5839 new_name_hash = fsp->name_hash;
5843 if (!did_rename) {
5844 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5845 "for %s\n", file_id_string_tos(&lck->id),
5846 smb_fname_str_dbg(smb_fname_dst)));
5849 /* Send messages to all smbd's (not ourself) that the name has changed. */
5850 rename_share_filename(conn->sconn->msg_ctx, lck, conn->connectpath,
5851 orig_name_hash, new_name_hash,
5852 smb_fname_dst);
5856 /****************************************************************************
5857 We need to check if the source path is a parent directory of the destination
5858 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5859 refuse the rename with a sharing violation. Under UNIX the above call can
5860 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5861 probably need to check that the client is a Windows one before disallowing
5862 this as a UNIX client (one with UNIX extensions) can know the source is a
5863 symlink and make this decision intelligently. Found by an excellent bug
5864 report from <AndyLiebman@aol.com>.
5865 ****************************************************************************/
5867 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5868 const struct smb_filename *smb_fname_dst)
5870 const char *psrc = smb_fname_src->base_name;
5871 const char *pdst = smb_fname_dst->base_name;
5872 size_t slen;
5874 if (psrc[0] == '.' && psrc[1] == '/') {
5875 psrc += 2;
5877 if (pdst[0] == '.' && pdst[1] == '/') {
5878 pdst += 2;
5880 if ((slen = strlen(psrc)) > strlen(pdst)) {
5881 return False;
5883 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5887 * Do the notify calls from a rename
5890 static void notify_rename(connection_struct *conn, bool is_dir,
5891 const struct smb_filename *smb_fname_src,
5892 const struct smb_filename *smb_fname_dst)
5894 char *parent_dir_src = NULL;
5895 char *parent_dir_dst = NULL;
5896 uint32 mask;
5898 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5899 : FILE_NOTIFY_CHANGE_FILE_NAME;
5901 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5902 &parent_dir_src, NULL) ||
5903 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5904 &parent_dir_dst, NULL)) {
5905 goto out;
5908 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5909 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5910 smb_fname_src->base_name);
5911 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5912 smb_fname_dst->base_name);
5914 else {
5915 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5916 smb_fname_src->base_name);
5917 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5918 smb_fname_dst->base_name);
5921 /* this is a strange one. w2k3 gives an additional event for
5922 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5923 files, but not directories */
5924 if (!is_dir) {
5925 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5926 FILE_NOTIFY_CHANGE_ATTRIBUTES
5927 |FILE_NOTIFY_CHANGE_CREATION,
5928 smb_fname_dst->base_name);
5930 out:
5931 TALLOC_FREE(parent_dir_src);
5932 TALLOC_FREE(parent_dir_dst);
5935 /****************************************************************************
5936 Returns an error if the parent directory for a filename is open in an
5937 incompatible way.
5938 ****************************************************************************/
5940 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
5941 const struct smb_filename *smb_fname_dst_in)
5943 char *parent_dir = NULL;
5944 struct smb_filename smb_fname_parent;
5945 struct file_id id;
5946 files_struct *fsp = NULL;
5947 int ret;
5949 if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
5950 &parent_dir, NULL)) {
5951 return NT_STATUS_NO_MEMORY;
5953 ZERO_STRUCT(smb_fname_parent);
5954 smb_fname_parent.base_name = parent_dir;
5956 ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
5957 if (ret == -1) {
5958 return map_nt_error_from_unix(errno);
5962 * We're only checking on this smbd here, mostly good
5963 * enough.. and will pass tests.
5966 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
5967 for (fsp = file_find_di_first(conn->sconn, id); fsp;
5968 fsp = file_find_di_next(fsp)) {
5969 if (fsp->access_mask & DELETE_ACCESS) {
5970 return NT_STATUS_SHARING_VIOLATION;
5973 return NT_STATUS_OK;
5976 /****************************************************************************
5977 Rename an open file - given an fsp.
5978 ****************************************************************************/
5980 NTSTATUS rename_internals_fsp(connection_struct *conn,
5981 files_struct *fsp,
5982 const struct smb_filename *smb_fname_dst_in,
5983 uint32 attrs,
5984 bool replace_if_exists)
5986 TALLOC_CTX *ctx = talloc_tos();
5987 struct smb_filename *smb_fname_dst = NULL;
5988 NTSTATUS status = NT_STATUS_OK;
5989 struct share_mode_lock *lck = NULL;
5990 bool dst_exists, old_is_stream, new_is_stream;
5992 status = check_name(conn, smb_fname_dst_in->base_name);
5993 if (!NT_STATUS_IS_OK(status)) {
5994 return status;
5997 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
5998 if (!NT_STATUS_IS_OK(status)) {
5999 return status;
6002 /* Make a copy of the dst smb_fname structs */
6004 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
6005 if (!NT_STATUS_IS_OK(status)) {
6006 goto out;
6010 * Check for special case with case preserving and not
6011 * case sensitive. If the old last component differs from the original
6012 * last component only by case, then we should allow
6013 * the rename (user is trying to change the case of the
6014 * filename).
6016 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
6017 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6018 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6019 char *last_slash;
6020 char *fname_dst_lcomp_base_mod = NULL;
6021 struct smb_filename *smb_fname_orig_lcomp = NULL;
6024 * Get the last component of the destination name.
6026 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
6027 if (last_slash) {
6028 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
6029 } else {
6030 fname_dst_lcomp_base_mod = talloc_strdup(ctx, smb_fname_dst->base_name);
6032 if (!fname_dst_lcomp_base_mod) {
6033 status = NT_STATUS_NO_MEMORY;
6034 goto out;
6038 * Create an smb_filename struct using the original last
6039 * component of the destination.
6041 status = create_synthetic_smb_fname_split(ctx,
6042 smb_fname_dst->original_lcomp, NULL,
6043 &smb_fname_orig_lcomp);
6044 if (!NT_STATUS_IS_OK(status)) {
6045 TALLOC_FREE(fname_dst_lcomp_base_mod);
6046 goto out;
6049 /* If the base names only differ by case, use original. */
6050 if(!strcsequal(fname_dst_lcomp_base_mod,
6051 smb_fname_orig_lcomp->base_name)) {
6052 char *tmp;
6054 * Replace the modified last component with the
6055 * original.
6057 if (last_slash) {
6058 *last_slash = '\0'; /* Truncate at the '/' */
6059 tmp = talloc_asprintf(smb_fname_dst,
6060 "%s/%s",
6061 smb_fname_dst->base_name,
6062 smb_fname_orig_lcomp->base_name);
6063 } else {
6064 tmp = talloc_asprintf(smb_fname_dst,
6065 "%s",
6066 smb_fname_orig_lcomp->base_name);
6068 if (tmp == NULL) {
6069 status = NT_STATUS_NO_MEMORY;
6070 TALLOC_FREE(fname_dst_lcomp_base_mod);
6071 TALLOC_FREE(smb_fname_orig_lcomp);
6072 goto out;
6074 TALLOC_FREE(smb_fname_dst->base_name);
6075 smb_fname_dst->base_name = tmp;
6078 /* If the stream_names only differ by case, use original. */
6079 if(!strcsequal(smb_fname_dst->stream_name,
6080 smb_fname_orig_lcomp->stream_name)) {
6081 char *tmp = NULL;
6082 /* Use the original stream. */
6083 tmp = talloc_strdup(smb_fname_dst,
6084 smb_fname_orig_lcomp->stream_name);
6085 if (tmp == NULL) {
6086 status = NT_STATUS_NO_MEMORY;
6087 TALLOC_FREE(fname_dst_lcomp_base_mod);
6088 TALLOC_FREE(smb_fname_orig_lcomp);
6089 goto out;
6091 TALLOC_FREE(smb_fname_dst->stream_name);
6092 smb_fname_dst->stream_name = tmp;
6094 TALLOC_FREE(fname_dst_lcomp_base_mod);
6095 TALLOC_FREE(smb_fname_orig_lcomp);
6099 * If the src and dest names are identical - including case,
6100 * don't do the rename, just return success.
6103 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6104 strcsequal(fsp->fsp_name->stream_name,
6105 smb_fname_dst->stream_name)) {
6106 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6107 "- returning success\n",
6108 smb_fname_str_dbg(smb_fname_dst)));
6109 status = NT_STATUS_OK;
6110 goto out;
6113 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6114 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6116 /* Return the correct error code if both names aren't streams. */
6117 if (!old_is_stream && new_is_stream) {
6118 status = NT_STATUS_OBJECT_NAME_INVALID;
6119 goto out;
6122 if (old_is_stream && !new_is_stream) {
6123 status = NT_STATUS_INVALID_PARAMETER;
6124 goto out;
6127 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6129 if(!replace_if_exists && dst_exists) {
6130 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6131 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6132 smb_fname_str_dbg(smb_fname_dst)));
6133 status = NT_STATUS_OBJECT_NAME_COLLISION;
6134 goto out;
6137 if (dst_exists) {
6138 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6139 &smb_fname_dst->st);
6140 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6141 fileid);
6142 /* The file can be open when renaming a stream */
6143 if (dst_fsp && !new_is_stream) {
6144 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6145 status = NT_STATUS_ACCESS_DENIED;
6146 goto out;
6150 /* Ensure we have a valid stat struct for the source. */
6151 status = vfs_stat_fsp(fsp);
6152 if (!NT_STATUS_IS_OK(status)) {
6153 goto out;
6156 status = can_rename(conn, fsp, attrs);
6158 if (!NT_STATUS_IS_OK(status)) {
6159 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6160 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6161 smb_fname_str_dbg(smb_fname_dst)));
6162 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6163 status = NT_STATUS_ACCESS_DENIED;
6164 goto out;
6167 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6168 status = NT_STATUS_ACCESS_DENIED;
6171 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6172 NULL);
6175 * We have the file open ourselves, so not being able to get the
6176 * corresponding share mode lock is a fatal error.
6179 SMB_ASSERT(lck != NULL);
6181 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6182 uint32 create_options = fsp->fh->private_options;
6184 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6185 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6186 smb_fname_str_dbg(smb_fname_dst)));
6188 if (!fsp->is_directory &&
6189 !lp_posix_pathnames() &&
6190 (lp_map_archive(SNUM(conn)) ||
6191 lp_store_dos_attributes(SNUM(conn)))) {
6192 /* We must set the archive bit on the newly
6193 renamed file. */
6194 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6195 uint32_t old_dosmode = dos_mode(conn,
6196 smb_fname_dst);
6197 file_set_dosmode(conn,
6198 smb_fname_dst,
6199 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6200 NULL,
6201 true);
6205 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6206 smb_fname_dst);
6208 rename_open_files(conn, lck, fsp->name_hash, smb_fname_dst);
6211 * A rename acts as a new file create w.r.t. allowing an initial delete
6212 * on close, probably because in Windows there is a new handle to the
6213 * new file. If initial delete on close was requested but not
6214 * originally set, we need to set it here. This is probably not 100% correct,
6215 * but will work for the CIFSFS client which in non-posix mode
6216 * depends on these semantics. JRA.
6219 if (create_options & FILE_DELETE_ON_CLOSE) {
6220 status = can_set_delete_on_close(fsp, 0);
6222 if (NT_STATUS_IS_OK(status)) {
6223 /* Note that here we set the *inital* delete on close flag,
6224 * not the regular one. The magic gets handled in close. */
6225 fsp->initial_delete_on_close = True;
6228 TALLOC_FREE(lck);
6229 status = NT_STATUS_OK;
6230 goto out;
6233 TALLOC_FREE(lck);
6235 if (errno == ENOTDIR || errno == EISDIR) {
6236 status = NT_STATUS_OBJECT_NAME_COLLISION;
6237 } else {
6238 status = map_nt_error_from_unix(errno);
6241 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6242 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6243 smb_fname_str_dbg(smb_fname_dst)));
6245 out:
6246 TALLOC_FREE(smb_fname_dst);
6248 return status;
6251 /****************************************************************************
6252 The guts of the rename command, split out so it may be called by the NT SMB
6253 code.
6254 ****************************************************************************/
6256 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6257 connection_struct *conn,
6258 struct smb_request *req,
6259 struct smb_filename *smb_fname_src,
6260 struct smb_filename *smb_fname_dst,
6261 uint32 attrs,
6262 bool replace_if_exists,
6263 bool src_has_wild,
6264 bool dest_has_wild,
6265 uint32_t access_mask)
6267 char *fname_src_dir = NULL;
6268 char *fname_src_mask = NULL;
6269 int count=0;
6270 NTSTATUS status = NT_STATUS_OK;
6271 struct smb_Dir *dir_hnd = NULL;
6272 const char *dname = NULL;
6273 char *talloced = NULL;
6274 long offset = 0;
6275 int create_options = 0;
6276 bool posix_pathnames = lp_posix_pathnames();
6279 * Split the old name into directory and last component
6280 * strings. Note that unix_convert may have stripped off a
6281 * leading ./ from both name and newname if the rename is
6282 * at the root of the share. We need to make sure either both
6283 * name and newname contain a / character or neither of them do
6284 * as this is checked in resolve_wildcards().
6287 /* Split up the directory from the filename/mask. */
6288 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6289 &fname_src_dir, &fname_src_mask);
6290 if (!NT_STATUS_IS_OK(status)) {
6291 status = NT_STATUS_NO_MEMORY;
6292 goto out;
6296 * We should only check the mangled cache
6297 * here if unix_convert failed. This means
6298 * that the path in 'mask' doesn't exist
6299 * on the file system and so we need to look
6300 * for a possible mangle. This patch from
6301 * Tine Smukavec <valentin.smukavec@hermes.si>.
6304 if (!VALID_STAT(smb_fname_src->st) &&
6305 mangle_is_mangled(fname_src_mask, conn->params)) {
6306 char *new_mask = NULL;
6307 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6308 conn->params);
6309 if (new_mask) {
6310 TALLOC_FREE(fname_src_mask);
6311 fname_src_mask = new_mask;
6315 if (!src_has_wild) {
6316 files_struct *fsp;
6319 * Only one file needs to be renamed. Append the mask back
6320 * onto the directory.
6322 TALLOC_FREE(smb_fname_src->base_name);
6323 if (ISDOT(fname_src_dir)) {
6324 /* Ensure we use canonical names on open. */
6325 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6326 "%s",
6327 fname_src_mask);
6328 } else {
6329 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6330 "%s/%s",
6331 fname_src_dir,
6332 fname_src_mask);
6334 if (!smb_fname_src->base_name) {
6335 status = NT_STATUS_NO_MEMORY;
6336 goto out;
6339 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6340 "case_preserve = %d, short case preserve = %d, "
6341 "directory = %s, newname = %s, "
6342 "last_component_dest = %s\n",
6343 conn->case_sensitive, conn->case_preserve,
6344 conn->short_case_preserve,
6345 smb_fname_str_dbg(smb_fname_src),
6346 smb_fname_str_dbg(smb_fname_dst),
6347 smb_fname_dst->original_lcomp));
6349 /* The dest name still may have wildcards. */
6350 if (dest_has_wild) {
6351 char *fname_dst_mod = NULL;
6352 if (!resolve_wildcards(smb_fname_dst,
6353 smb_fname_src->base_name,
6354 smb_fname_dst->base_name,
6355 &fname_dst_mod)) {
6356 DEBUG(6, ("rename_internals: resolve_wildcards "
6357 "%s %s failed\n",
6358 smb_fname_src->base_name,
6359 smb_fname_dst->base_name));
6360 status = NT_STATUS_NO_MEMORY;
6361 goto out;
6363 TALLOC_FREE(smb_fname_dst->base_name);
6364 smb_fname_dst->base_name = fname_dst_mod;
6367 ZERO_STRUCT(smb_fname_src->st);
6368 if (posix_pathnames) {
6369 SMB_VFS_LSTAT(conn, smb_fname_src);
6370 } else {
6371 SMB_VFS_STAT(conn, smb_fname_src);
6374 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6375 create_options |= FILE_DIRECTORY_FILE;
6378 status = SMB_VFS_CREATE_FILE(
6379 conn, /* conn */
6380 req, /* req */
6381 0, /* root_dir_fid */
6382 smb_fname_src, /* fname */
6383 access_mask, /* access_mask */
6384 (FILE_SHARE_READ | /* share_access */
6385 FILE_SHARE_WRITE),
6386 FILE_OPEN, /* create_disposition*/
6387 create_options, /* create_options */
6388 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6389 0, /* oplock_request */
6390 0, /* allocation_size */
6391 0, /* private_flags */
6392 NULL, /* sd */
6393 NULL, /* ea_list */
6394 &fsp, /* result */
6395 NULL); /* pinfo */
6397 if (!NT_STATUS_IS_OK(status)) {
6398 DEBUG(3, ("Could not open rename source %s: %s\n",
6399 smb_fname_str_dbg(smb_fname_src),
6400 nt_errstr(status)));
6401 goto out;
6404 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6405 attrs, replace_if_exists);
6407 close_file(req, fsp, NORMAL_CLOSE);
6409 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6410 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6411 smb_fname_str_dbg(smb_fname_dst)));
6413 goto out;
6417 * Wildcards - process each file that matches.
6419 if (strequal(fname_src_mask, "????????.???")) {
6420 TALLOC_FREE(fname_src_mask);
6421 fname_src_mask = talloc_strdup(ctx, "*");
6422 if (!fname_src_mask) {
6423 status = NT_STATUS_NO_MEMORY;
6424 goto out;
6428 status = check_name(conn, fname_src_dir);
6429 if (!NT_STATUS_IS_OK(status)) {
6430 goto out;
6433 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6434 attrs);
6435 if (dir_hnd == NULL) {
6436 status = map_nt_error_from_unix(errno);
6437 goto out;
6440 status = NT_STATUS_NO_SUCH_FILE;
6442 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6443 * - gentest fix. JRA
6446 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6447 &talloced))) {
6448 files_struct *fsp = NULL;
6449 char *destname = NULL;
6450 bool sysdir_entry = False;
6452 /* Quick check for "." and ".." */
6453 if (ISDOT(dname) || ISDOTDOT(dname)) {
6454 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
6455 sysdir_entry = True;
6456 } else {
6457 TALLOC_FREE(talloced);
6458 continue;
6462 if (!is_visible_file(conn, fname_src_dir, dname,
6463 &smb_fname_src->st, false)) {
6464 TALLOC_FREE(talloced);
6465 continue;
6468 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6469 TALLOC_FREE(talloced);
6470 continue;
6473 if (sysdir_entry) {
6474 status = NT_STATUS_OBJECT_NAME_INVALID;
6475 break;
6478 TALLOC_FREE(smb_fname_src->base_name);
6479 if (ISDOT(fname_src_dir)) {
6480 /* Ensure we use canonical names on open. */
6481 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6482 "%s",
6483 dname);
6484 } else {
6485 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6486 "%s/%s",
6487 fname_src_dir,
6488 dname);
6490 if (!smb_fname_src->base_name) {
6491 status = NT_STATUS_NO_MEMORY;
6492 goto out;
6495 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6496 smb_fname_dst->base_name,
6497 &destname)) {
6498 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6499 smb_fname_src->base_name, destname));
6500 TALLOC_FREE(talloced);
6501 continue;
6503 if (!destname) {
6504 status = NT_STATUS_NO_MEMORY;
6505 goto out;
6508 TALLOC_FREE(smb_fname_dst->base_name);
6509 smb_fname_dst->base_name = destname;
6511 ZERO_STRUCT(smb_fname_src->st);
6512 if (posix_pathnames) {
6513 SMB_VFS_LSTAT(conn, smb_fname_src);
6514 } else {
6515 SMB_VFS_STAT(conn, smb_fname_src);
6518 create_options = 0;
6520 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6521 create_options |= FILE_DIRECTORY_FILE;
6524 status = SMB_VFS_CREATE_FILE(
6525 conn, /* conn */
6526 req, /* req */
6527 0, /* root_dir_fid */
6528 smb_fname_src, /* fname */
6529 access_mask, /* access_mask */
6530 (FILE_SHARE_READ | /* share_access */
6531 FILE_SHARE_WRITE),
6532 FILE_OPEN, /* create_disposition*/
6533 create_options, /* create_options */
6534 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6535 0, /* oplock_request */
6536 0, /* allocation_size */
6537 0, /* private_flags */
6538 NULL, /* sd */
6539 NULL, /* ea_list */
6540 &fsp, /* result */
6541 NULL); /* pinfo */
6543 if (!NT_STATUS_IS_OK(status)) {
6544 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6545 "returned %s rename %s -> %s\n",
6546 nt_errstr(status),
6547 smb_fname_str_dbg(smb_fname_src),
6548 smb_fname_str_dbg(smb_fname_dst)));
6549 break;
6552 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6553 dname);
6554 if (!smb_fname_dst->original_lcomp) {
6555 status = NT_STATUS_NO_MEMORY;
6556 goto out;
6559 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6560 attrs, replace_if_exists);
6562 close_file(req, fsp, NORMAL_CLOSE);
6564 if (!NT_STATUS_IS_OK(status)) {
6565 DEBUG(3, ("rename_internals_fsp returned %s for "
6566 "rename %s -> %s\n", nt_errstr(status),
6567 smb_fname_str_dbg(smb_fname_src),
6568 smb_fname_str_dbg(smb_fname_dst)));
6569 break;
6572 count++;
6574 DEBUG(3,("rename_internals: doing rename on %s -> "
6575 "%s\n", smb_fname_str_dbg(smb_fname_src),
6576 smb_fname_str_dbg(smb_fname_src)));
6577 TALLOC_FREE(talloced);
6579 TALLOC_FREE(dir_hnd);
6581 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6582 status = map_nt_error_from_unix(errno);
6585 out:
6586 TALLOC_FREE(talloced);
6587 TALLOC_FREE(fname_src_dir);
6588 TALLOC_FREE(fname_src_mask);
6589 return status;
6592 /****************************************************************************
6593 Reply to a mv.
6594 ****************************************************************************/
6596 void reply_mv(struct smb_request *req)
6598 connection_struct *conn = req->conn;
6599 char *name = NULL;
6600 char *newname = NULL;
6601 const char *p;
6602 uint32 attrs;
6603 NTSTATUS status;
6604 bool src_has_wcard = False;
6605 bool dest_has_wcard = False;
6606 TALLOC_CTX *ctx = talloc_tos();
6607 struct smb_filename *smb_fname_src = NULL;
6608 struct smb_filename *smb_fname_dst = NULL;
6609 uint32_t src_ucf_flags = lp_posix_pathnames() ? UCF_UNIX_NAME_LOOKUP : UCF_COND_ALLOW_WCARD_LCOMP;
6610 uint32_t dst_ucf_flags = UCF_SAVE_LCOMP | (lp_posix_pathnames() ? 0 : UCF_COND_ALLOW_WCARD_LCOMP);
6611 bool stream_rename = false;
6613 START_PROFILE(SMBmv);
6615 if (req->wct < 1) {
6616 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6617 goto out;
6620 attrs = SVAL(req->vwv+0, 0);
6622 p = (const char *)req->buf + 1;
6623 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6624 &status, &src_has_wcard);
6625 if (!NT_STATUS_IS_OK(status)) {
6626 reply_nterror(req, status);
6627 goto out;
6629 p++;
6630 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6631 &status, &dest_has_wcard);
6632 if (!NT_STATUS_IS_OK(status)) {
6633 reply_nterror(req, status);
6634 goto out;
6637 if (!lp_posix_pathnames()) {
6638 /* The newname must begin with a ':' if the
6639 name contains a ':'. */
6640 if (strchr_m(name, ':')) {
6641 if (newname[0] != ':') {
6642 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6643 goto out;
6645 stream_rename = true;
6649 status = filename_convert(ctx,
6650 conn,
6651 req->flags2 & FLAGS2_DFS_PATHNAMES,
6652 name,
6653 src_ucf_flags,
6654 &src_has_wcard,
6655 &smb_fname_src);
6657 if (!NT_STATUS_IS_OK(status)) {
6658 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6659 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6660 ERRSRV, ERRbadpath);
6661 goto out;
6663 reply_nterror(req, status);
6664 goto out;
6667 status = filename_convert(ctx,
6668 conn,
6669 req->flags2 & FLAGS2_DFS_PATHNAMES,
6670 newname,
6671 dst_ucf_flags,
6672 &dest_has_wcard,
6673 &smb_fname_dst);
6675 if (!NT_STATUS_IS_OK(status)) {
6676 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6677 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6678 ERRSRV, ERRbadpath);
6679 goto out;
6681 reply_nterror(req, status);
6682 goto out;
6685 if (stream_rename) {
6686 /* smb_fname_dst->base_name must be the same as
6687 smb_fname_src->base_name. */
6688 TALLOC_FREE(smb_fname_dst->base_name);
6689 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
6690 smb_fname_src->base_name);
6691 if (!smb_fname_dst->base_name) {
6692 reply_nterror(req, NT_STATUS_NO_MEMORY);
6693 goto out;
6697 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6698 smb_fname_str_dbg(smb_fname_dst)));
6700 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6701 attrs, False, src_has_wcard, dest_has_wcard,
6702 DELETE_ACCESS);
6703 if (!NT_STATUS_IS_OK(status)) {
6704 if (open_was_deferred(req->mid)) {
6705 /* We have re-scheduled this call. */
6706 goto out;
6708 reply_nterror(req, status);
6709 goto out;
6712 reply_outbuf(req, 0, 0);
6713 out:
6714 TALLOC_FREE(smb_fname_src);
6715 TALLOC_FREE(smb_fname_dst);
6716 END_PROFILE(SMBmv);
6717 return;
6720 /*******************************************************************
6721 Copy a file as part of a reply_copy.
6722 ******************************************************************/
6725 * TODO: check error codes on all callers
6728 NTSTATUS copy_file(TALLOC_CTX *ctx,
6729 connection_struct *conn,
6730 struct smb_filename *smb_fname_src,
6731 struct smb_filename *smb_fname_dst,
6732 int ofun,
6733 int count,
6734 bool target_is_directory)
6736 struct smb_filename *smb_fname_dst_tmp = NULL;
6737 SMB_OFF_T ret=-1;
6738 files_struct *fsp1,*fsp2;
6739 uint32 dosattrs;
6740 uint32 new_create_disposition;
6741 NTSTATUS status;
6744 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6745 if (!NT_STATUS_IS_OK(status)) {
6746 return status;
6750 * If the target is a directory, extract the last component from the
6751 * src filename and append it to the dst filename
6753 if (target_is_directory) {
6754 const char *p;
6756 /* dest/target can't be a stream if it's a directory. */
6757 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6759 p = strrchr_m(smb_fname_src->base_name,'/');
6760 if (p) {
6761 p++;
6762 } else {
6763 p = smb_fname_src->base_name;
6765 smb_fname_dst_tmp->base_name =
6766 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6768 if (!smb_fname_dst_tmp->base_name) {
6769 status = NT_STATUS_NO_MEMORY;
6770 goto out;
6774 status = vfs_file_exist(conn, smb_fname_src);
6775 if (!NT_STATUS_IS_OK(status)) {
6776 goto out;
6779 if (!target_is_directory && count) {
6780 new_create_disposition = FILE_OPEN;
6781 } else {
6782 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
6783 0, ofun,
6784 NULL, NULL,
6785 &new_create_disposition,
6786 NULL,
6787 NULL)) {
6788 status = NT_STATUS_INVALID_PARAMETER;
6789 goto out;
6793 /* Open the src file for reading. */
6794 status = SMB_VFS_CREATE_FILE(
6795 conn, /* conn */
6796 NULL, /* req */
6797 0, /* root_dir_fid */
6798 smb_fname_src, /* fname */
6799 FILE_GENERIC_READ, /* access_mask */
6800 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6801 FILE_OPEN, /* create_disposition*/
6802 0, /* create_options */
6803 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6804 INTERNAL_OPEN_ONLY, /* oplock_request */
6805 0, /* allocation_size */
6806 0, /* private_flags */
6807 NULL, /* sd */
6808 NULL, /* ea_list */
6809 &fsp1, /* result */
6810 NULL); /* psbuf */
6812 if (!NT_STATUS_IS_OK(status)) {
6813 goto out;
6816 dosattrs = dos_mode(conn, smb_fname_src);
6818 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6819 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6822 /* Open the dst file for writing. */
6823 status = SMB_VFS_CREATE_FILE(
6824 conn, /* conn */
6825 NULL, /* req */
6826 0, /* root_dir_fid */
6827 smb_fname_dst, /* fname */
6828 FILE_GENERIC_WRITE, /* access_mask */
6829 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6830 new_create_disposition, /* create_disposition*/
6831 0, /* create_options */
6832 dosattrs, /* file_attributes */
6833 INTERNAL_OPEN_ONLY, /* oplock_request */
6834 0, /* allocation_size */
6835 0, /* private_flags */
6836 NULL, /* sd */
6837 NULL, /* ea_list */
6838 &fsp2, /* result */
6839 NULL); /* psbuf */
6841 if (!NT_STATUS_IS_OK(status)) {
6842 close_file(NULL, fsp1, ERROR_CLOSE);
6843 goto out;
6846 if (ofun & OPENX_FILE_EXISTS_OPEN) {
6847 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
6848 if (ret == -1) {
6849 DEBUG(0, ("error - vfs lseek returned error %s\n",
6850 strerror(errno)));
6851 status = map_nt_error_from_unix(errno);
6852 close_file(NULL, fsp1, ERROR_CLOSE);
6853 close_file(NULL, fsp2, ERROR_CLOSE);
6854 goto out;
6858 /* Do the actual copy. */
6859 if (smb_fname_src->st.st_ex_size) {
6860 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6861 } else {
6862 ret = 0;
6865 close_file(NULL, fsp1, NORMAL_CLOSE);
6867 /* Ensure the modtime is set correctly on the destination file. */
6868 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6871 * As we are opening fsp1 read-only we only expect
6872 * an error on close on fsp2 if we are out of space.
6873 * Thus we don't look at the error return from the
6874 * close of fsp1.
6876 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6878 if (!NT_STATUS_IS_OK(status)) {
6879 goto out;
6882 if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6883 status = NT_STATUS_DISK_FULL;
6884 goto out;
6887 status = NT_STATUS_OK;
6889 out:
6890 TALLOC_FREE(smb_fname_dst_tmp);
6891 return status;
6894 /****************************************************************************
6895 Reply to a file copy.
6896 ****************************************************************************/
6898 void reply_copy(struct smb_request *req)
6900 connection_struct *conn = req->conn;
6901 struct smb_filename *smb_fname_src = NULL;
6902 struct smb_filename *smb_fname_dst = NULL;
6903 char *fname_src = NULL;
6904 char *fname_dst = NULL;
6905 char *fname_src_mask = NULL;
6906 char *fname_src_dir = NULL;
6907 const char *p;
6908 int count=0;
6909 int error = ERRnoaccess;
6910 int tid2;
6911 int ofun;
6912 int flags;
6913 bool target_is_directory=False;
6914 bool source_has_wild = False;
6915 bool dest_has_wild = False;
6916 NTSTATUS status;
6917 TALLOC_CTX *ctx = talloc_tos();
6919 START_PROFILE(SMBcopy);
6921 if (req->wct < 3) {
6922 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6923 goto out;
6926 tid2 = SVAL(req->vwv+0, 0);
6927 ofun = SVAL(req->vwv+1, 0);
6928 flags = SVAL(req->vwv+2, 0);
6930 p = (const char *)req->buf;
6931 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6932 &status, &source_has_wild);
6933 if (!NT_STATUS_IS_OK(status)) {
6934 reply_nterror(req, status);
6935 goto out;
6937 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6938 &status, &dest_has_wild);
6939 if (!NT_STATUS_IS_OK(status)) {
6940 reply_nterror(req, status);
6941 goto out;
6944 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6946 if (tid2 != conn->cnum) {
6947 /* can't currently handle inter share copies XXXX */
6948 DEBUG(3,("Rejecting inter-share copy\n"));
6949 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
6950 goto out;
6953 status = filename_convert(ctx, conn,
6954 req->flags2 & FLAGS2_DFS_PATHNAMES,
6955 fname_src,
6956 UCF_COND_ALLOW_WCARD_LCOMP,
6957 &source_has_wild,
6958 &smb_fname_src);
6959 if (!NT_STATUS_IS_OK(status)) {
6960 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6961 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6962 ERRSRV, ERRbadpath);
6963 goto out;
6965 reply_nterror(req, status);
6966 goto out;
6969 status = filename_convert(ctx, conn,
6970 req->flags2 & FLAGS2_DFS_PATHNAMES,
6971 fname_dst,
6972 UCF_COND_ALLOW_WCARD_LCOMP,
6973 &dest_has_wild,
6974 &smb_fname_dst);
6975 if (!NT_STATUS_IS_OK(status)) {
6976 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6977 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6978 ERRSRV, ERRbadpath);
6979 goto out;
6981 reply_nterror(req, status);
6982 goto out;
6985 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6987 if ((flags&1) && target_is_directory) {
6988 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
6989 goto out;
6992 if ((flags&2) && !target_is_directory) {
6993 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
6994 goto out;
6997 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6998 /* wants a tree copy! XXXX */
6999 DEBUG(3,("Rejecting tree copy\n"));
7000 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7001 goto out;
7004 /* Split up the directory from the filename/mask. */
7005 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7006 &fname_src_dir, &fname_src_mask);
7007 if (!NT_STATUS_IS_OK(status)) {
7008 reply_nterror(req, NT_STATUS_NO_MEMORY);
7009 goto out;
7013 * We should only check the mangled cache
7014 * here if unix_convert failed. This means
7015 * that the path in 'mask' doesn't exist
7016 * on the file system and so we need to look
7017 * for a possible mangle. This patch from
7018 * Tine Smukavec <valentin.smukavec@hermes.si>.
7020 if (!VALID_STAT(smb_fname_src->st) &&
7021 mangle_is_mangled(fname_src_mask, conn->params)) {
7022 char *new_mask = NULL;
7023 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
7024 &new_mask, conn->params);
7026 /* Use demangled name if one was successfully found. */
7027 if (new_mask) {
7028 TALLOC_FREE(fname_src_mask);
7029 fname_src_mask = new_mask;
7033 if (!source_has_wild) {
7036 * Only one file needs to be copied. Append the mask back onto
7037 * the directory.
7039 TALLOC_FREE(smb_fname_src->base_name);
7040 if (ISDOT(fname_src_dir)) {
7041 /* Ensure we use canonical names on open. */
7042 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7043 "%s",
7044 fname_src_mask);
7045 } else {
7046 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7047 "%s/%s",
7048 fname_src_dir,
7049 fname_src_mask);
7051 if (!smb_fname_src->base_name) {
7052 reply_nterror(req, NT_STATUS_NO_MEMORY);
7053 goto out;
7056 if (dest_has_wild) {
7057 char *fname_dst_mod = NULL;
7058 if (!resolve_wildcards(smb_fname_dst,
7059 smb_fname_src->base_name,
7060 smb_fname_dst->base_name,
7061 &fname_dst_mod)) {
7062 reply_nterror(req, NT_STATUS_NO_MEMORY);
7063 goto out;
7065 TALLOC_FREE(smb_fname_dst->base_name);
7066 smb_fname_dst->base_name = fname_dst_mod;
7069 status = check_name(conn, smb_fname_src->base_name);
7070 if (!NT_STATUS_IS_OK(status)) {
7071 reply_nterror(req, status);
7072 goto out;
7075 status = check_name(conn, smb_fname_dst->base_name);
7076 if (!NT_STATUS_IS_OK(status)) {
7077 reply_nterror(req, status);
7078 goto out;
7081 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7082 ofun, count, target_is_directory);
7084 if(!NT_STATUS_IS_OK(status)) {
7085 reply_nterror(req, status);
7086 goto out;
7087 } else {
7088 count++;
7090 } else {
7091 struct smb_Dir *dir_hnd = NULL;
7092 const char *dname = NULL;
7093 char *talloced = NULL;
7094 long offset = 0;
7097 * There is a wildcard that requires us to actually read the
7098 * src dir and copy each file matching the mask to the dst.
7099 * Right now streams won't be copied, but this could
7100 * presumably be added with a nested loop for reach dir entry.
7102 SMB_ASSERT(!smb_fname_src->stream_name);
7103 SMB_ASSERT(!smb_fname_dst->stream_name);
7105 smb_fname_src->stream_name = NULL;
7106 smb_fname_dst->stream_name = NULL;
7108 if (strequal(fname_src_mask,"????????.???")) {
7109 TALLOC_FREE(fname_src_mask);
7110 fname_src_mask = talloc_strdup(ctx, "*");
7111 if (!fname_src_mask) {
7112 reply_nterror(req, NT_STATUS_NO_MEMORY);
7113 goto out;
7117 status = check_name(conn, fname_src_dir);
7118 if (!NT_STATUS_IS_OK(status)) {
7119 reply_nterror(req, status);
7120 goto out;
7123 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
7124 if (dir_hnd == NULL) {
7125 status = map_nt_error_from_unix(errno);
7126 reply_nterror(req, status);
7127 goto out;
7130 error = ERRbadfile;
7132 /* Iterate over the src dir copying each entry to the dst. */
7133 while ((dname = ReadDirName(dir_hnd, &offset,
7134 &smb_fname_src->st, &talloced))) {
7135 char *destname = NULL;
7137 if (ISDOT(dname) || ISDOTDOT(dname)) {
7138 TALLOC_FREE(talloced);
7139 continue;
7142 if (!is_visible_file(conn, fname_src_dir, dname,
7143 &smb_fname_src->st, false)) {
7144 TALLOC_FREE(talloced);
7145 continue;
7148 if(!mask_match(dname, fname_src_mask,
7149 conn->case_sensitive)) {
7150 TALLOC_FREE(talloced);
7151 continue;
7154 error = ERRnoaccess;
7156 /* Get the src smb_fname struct setup. */
7157 TALLOC_FREE(smb_fname_src->base_name);
7158 if (ISDOT(fname_src_dir)) {
7159 /* Ensure we use canonical names on open. */
7160 smb_fname_src->base_name =
7161 talloc_asprintf(smb_fname_src, "%s",
7162 dname);
7163 } else {
7164 smb_fname_src->base_name =
7165 talloc_asprintf(smb_fname_src, "%s/%s",
7166 fname_src_dir, dname);
7169 if (!smb_fname_src->base_name) {
7170 TALLOC_FREE(dir_hnd);
7171 TALLOC_FREE(talloced);
7172 reply_nterror(req, NT_STATUS_NO_MEMORY);
7173 goto out;
7176 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7177 smb_fname_dst->base_name,
7178 &destname)) {
7179 TALLOC_FREE(talloced);
7180 continue;
7182 if (!destname) {
7183 TALLOC_FREE(dir_hnd);
7184 TALLOC_FREE(talloced);
7185 reply_nterror(req, NT_STATUS_NO_MEMORY);
7186 goto out;
7189 TALLOC_FREE(smb_fname_dst->base_name);
7190 smb_fname_dst->base_name = destname;
7192 status = check_name(conn, smb_fname_src->base_name);
7193 if (!NT_STATUS_IS_OK(status)) {
7194 TALLOC_FREE(dir_hnd);
7195 TALLOC_FREE(talloced);
7196 reply_nterror(req, status);
7197 goto out;
7200 status = check_name(conn, smb_fname_dst->base_name);
7201 if (!NT_STATUS_IS_OK(status)) {
7202 TALLOC_FREE(dir_hnd);
7203 TALLOC_FREE(talloced);
7204 reply_nterror(req, status);
7205 goto out;
7208 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7209 smb_fname_src->base_name,
7210 smb_fname_dst->base_name));
7212 status = copy_file(ctx, conn, smb_fname_src,
7213 smb_fname_dst, ofun, count,
7214 target_is_directory);
7215 if (NT_STATUS_IS_OK(status)) {
7216 count++;
7219 TALLOC_FREE(talloced);
7221 TALLOC_FREE(dir_hnd);
7224 if (count == 0) {
7225 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7226 goto out;
7229 reply_outbuf(req, 1, 0);
7230 SSVAL(req->outbuf,smb_vwv0,count);
7231 out:
7232 TALLOC_FREE(smb_fname_src);
7233 TALLOC_FREE(smb_fname_dst);
7234 TALLOC_FREE(fname_src);
7235 TALLOC_FREE(fname_dst);
7236 TALLOC_FREE(fname_src_mask);
7237 TALLOC_FREE(fname_src_dir);
7239 END_PROFILE(SMBcopy);
7240 return;
7243 #undef DBGC_CLASS
7244 #define DBGC_CLASS DBGC_LOCKING
7246 /****************************************************************************
7247 Get a lock pid, dealing with large count requests.
7248 ****************************************************************************/
7250 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7251 bool large_file_format)
7253 if(!large_file_format)
7254 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7255 else
7256 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7259 /****************************************************************************
7260 Get a lock count, dealing with large count requests.
7261 ****************************************************************************/
7263 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7264 bool large_file_format)
7266 uint64_t count = 0;
7268 if(!large_file_format) {
7269 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7270 } else {
7272 #if defined(HAVE_LONGLONG)
7273 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7274 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7275 #else /* HAVE_LONGLONG */
7278 * NT4.x seems to be broken in that it sends large file (64 bit)
7279 * lockingX calls even if the CAP_LARGE_FILES was *not*
7280 * negotiated. For boxes without large unsigned ints truncate the
7281 * lock count by dropping the top 32 bits.
7284 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7285 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7286 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7287 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7288 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7291 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7292 #endif /* HAVE_LONGLONG */
7295 return count;
7298 #if !defined(HAVE_LONGLONG)
7299 /****************************************************************************
7300 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7301 ****************************************************************************/
7303 static uint32 map_lock_offset(uint32 high, uint32 low)
7305 unsigned int i;
7306 uint32 mask = 0;
7307 uint32 highcopy = high;
7310 * Try and find out how many significant bits there are in high.
7313 for(i = 0; highcopy; i++)
7314 highcopy >>= 1;
7317 * We use 31 bits not 32 here as POSIX
7318 * lock offsets may not be negative.
7321 mask = (~0) << (31 - i);
7323 if(low & mask)
7324 return 0; /* Fail. */
7326 high <<= (31 - i);
7328 return (high|low);
7330 #endif /* !defined(HAVE_LONGLONG) */
7332 /****************************************************************************
7333 Get a lock offset, dealing with large offset requests.
7334 ****************************************************************************/
7336 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7337 bool large_file_format, bool *err)
7339 uint64_t offset = 0;
7341 *err = False;
7343 if(!large_file_format) {
7344 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7345 } else {
7347 #if defined(HAVE_LONGLONG)
7348 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7349 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7350 #else /* HAVE_LONGLONG */
7353 * NT4.x seems to be broken in that it sends large file (64 bit)
7354 * lockingX calls even if the CAP_LARGE_FILES was *not*
7355 * negotiated. For boxes without large unsigned ints mangle the
7356 * lock offset by mapping the top 32 bits onto the lower 32.
7359 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7360 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7361 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7362 uint32 new_low = 0;
7364 if((new_low = map_lock_offset(high, low)) == 0) {
7365 *err = True;
7366 return (uint64_t)-1;
7369 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7370 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7371 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7372 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7375 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7376 #endif /* HAVE_LONGLONG */
7379 return offset;
7382 NTSTATUS smbd_do_locking(struct smb_request *req,
7383 files_struct *fsp,
7384 uint8_t type,
7385 int32_t timeout,
7386 uint16_t num_ulocks,
7387 struct smbd_lock_element *ulocks,
7388 uint16_t num_locks,
7389 struct smbd_lock_element *locks,
7390 bool *async)
7392 connection_struct *conn = req->conn;
7393 int i;
7394 NTSTATUS status = NT_STATUS_OK;
7396 *async = false;
7398 /* Data now points at the beginning of the list
7399 of smb_unlkrng structs */
7400 for(i = 0; i < (int)num_ulocks; i++) {
7401 struct smbd_lock_element *e = &ulocks[i];
7403 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7404 "pid %u, file %s\n",
7405 (double)e->offset,
7406 (double)e->count,
7407 (unsigned int)e->smblctx,
7408 fsp_str_dbg(fsp)));
7410 if (e->brltype != UNLOCK_LOCK) {
7411 /* this can only happen with SMB2 */
7412 return NT_STATUS_INVALID_PARAMETER;
7415 status = do_unlock(req->sconn->msg_ctx,
7416 fsp,
7417 e->smblctx,
7418 e->count,
7419 e->offset,
7420 WINDOWS_LOCK);
7422 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7423 nt_errstr(status)));
7425 if (!NT_STATUS_IS_OK(status)) {
7426 return status;
7430 /* Setup the timeout in seconds. */
7432 if (!lp_blocking_locks(SNUM(conn))) {
7433 timeout = 0;
7436 /* Data now points at the beginning of the list
7437 of smb_lkrng structs */
7439 for(i = 0; i < (int)num_locks; i++) {
7440 struct smbd_lock_element *e = &locks[i];
7442 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7443 "%llu, file %s timeout = %d\n",
7444 (double)e->offset,
7445 (double)e->count,
7446 (unsigned long long)e->smblctx,
7447 fsp_str_dbg(fsp),
7448 (int)timeout));
7450 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7451 struct blocking_lock_record *blr = NULL;
7453 if (num_locks > 1) {
7455 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7456 * if the lock vector contains one entry. When given mutliple cancel
7457 * requests in a single PDU we expect the server to return an
7458 * error. Windows servers seem to accept the request but only
7459 * cancel the first lock.
7460 * JRA - Do what Windows does (tm) :-).
7463 #if 0
7464 /* MS-CIFS (2.2.4.32.1) behavior. */
7465 return NT_STATUS_DOS(ERRDOS,
7466 ERRcancelviolation);
7467 #else
7468 /* Windows behavior. */
7469 if (i != 0) {
7470 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7471 "cancel request\n"));
7472 continue;
7474 #endif
7477 if (lp_blocking_locks(SNUM(conn))) {
7479 /* Schedule a message to ourselves to
7480 remove the blocking lock record and
7481 return the right error. */
7483 blr = blocking_lock_cancel_smb1(fsp,
7484 e->smblctx,
7485 e->offset,
7486 e->count,
7487 WINDOWS_LOCK,
7488 type,
7489 NT_STATUS_FILE_LOCK_CONFLICT);
7490 if (blr == NULL) {
7491 return NT_STATUS_DOS(
7492 ERRDOS,
7493 ERRcancelviolation);
7496 /* Remove a matching pending lock. */
7497 status = do_lock_cancel(fsp,
7498 e->smblctx,
7499 e->count,
7500 e->offset,
7501 WINDOWS_LOCK,
7502 blr);
7503 } else {
7504 bool blocking_lock = timeout ? true : false;
7505 bool defer_lock = false;
7506 struct byte_range_lock *br_lck;
7507 uint64_t block_smblctx;
7509 br_lck = do_lock(req->sconn->msg_ctx,
7510 fsp,
7511 e->smblctx,
7512 e->count,
7513 e->offset,
7514 e->brltype,
7515 WINDOWS_LOCK,
7516 blocking_lock,
7517 &status,
7518 &block_smblctx,
7519 NULL);
7521 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7522 /* Windows internal resolution for blocking locks seems
7523 to be about 200ms... Don't wait for less than that. JRA. */
7524 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7525 timeout = lp_lock_spin_time();
7527 defer_lock = true;
7530 /* If a lock sent with timeout of zero would fail, and
7531 * this lock has been requested multiple times,
7532 * according to brl_lock_failed() we convert this
7533 * request to a blocking lock with a timeout of between
7534 * 150 - 300 milliseconds.
7536 * If lp_lock_spin_time() has been set to 0, we skip
7537 * this blocking retry and fail immediately.
7539 * Replacement for do_lock_spin(). JRA. */
7541 if (!req->sconn->using_smb2 &&
7542 br_lck && lp_blocking_locks(SNUM(conn)) &&
7543 lp_lock_spin_time() && !blocking_lock &&
7544 NT_STATUS_EQUAL((status),
7545 NT_STATUS_FILE_LOCK_CONFLICT))
7547 defer_lock = true;
7548 timeout = lp_lock_spin_time();
7551 if (br_lck && defer_lock) {
7553 * A blocking lock was requested. Package up
7554 * this smb into a queued request and push it
7555 * onto the blocking lock queue.
7557 if(push_blocking_lock_request(br_lck,
7558 req,
7559 fsp,
7560 timeout,
7562 e->smblctx,
7563 e->brltype,
7564 WINDOWS_LOCK,
7565 e->offset,
7566 e->count,
7567 block_smblctx)) {
7568 TALLOC_FREE(br_lck);
7569 *async = true;
7570 return NT_STATUS_OK;
7574 TALLOC_FREE(br_lck);
7577 if (!NT_STATUS_IS_OK(status)) {
7578 break;
7582 /* If any of the above locks failed, then we must unlock
7583 all of the previous locks (X/Open spec). */
7585 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7587 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7588 i = -1; /* we want to skip the for loop */
7592 * Ensure we don't do a remove on the lock that just failed,
7593 * as under POSIX rules, if we have a lock already there, we
7594 * will delete it (and we shouldn't) .....
7596 for(i--; i >= 0; i--) {
7597 struct smbd_lock_element *e = &locks[i];
7599 do_unlock(req->sconn->msg_ctx,
7600 fsp,
7601 e->smblctx,
7602 e->count,
7603 e->offset,
7604 WINDOWS_LOCK);
7606 return status;
7609 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7610 fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7612 return NT_STATUS_OK;
7615 /****************************************************************************
7616 Reply to a lockingX request.
7617 ****************************************************************************/
7619 void reply_lockingX(struct smb_request *req)
7621 connection_struct *conn = req->conn;
7622 files_struct *fsp;
7623 unsigned char locktype;
7624 unsigned char oplocklevel;
7625 uint16 num_ulocks;
7626 uint16 num_locks;
7627 int32 lock_timeout;
7628 int i;
7629 const uint8_t *data;
7630 bool large_file_format;
7631 bool err;
7632 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7633 struct smbd_lock_element *ulocks;
7634 struct smbd_lock_element *locks;
7635 bool async = false;
7637 START_PROFILE(SMBlockingX);
7639 if (req->wct < 8) {
7640 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7641 END_PROFILE(SMBlockingX);
7642 return;
7645 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7646 locktype = CVAL(req->vwv+3, 0);
7647 oplocklevel = CVAL(req->vwv+3, 1);
7648 num_ulocks = SVAL(req->vwv+6, 0);
7649 num_locks = SVAL(req->vwv+7, 0);
7650 lock_timeout = IVAL(req->vwv+4, 0);
7651 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7653 if (!check_fsp(conn, req, fsp)) {
7654 END_PROFILE(SMBlockingX);
7655 return;
7658 data = req->buf;
7660 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7661 /* we don't support these - and CANCEL_LOCK makes w2k
7662 and XP reboot so I don't really want to be
7663 compatible! (tridge) */
7664 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7665 END_PROFILE(SMBlockingX);
7666 return;
7669 /* Check if this is an oplock break on a file
7670 we have granted an oplock on.
7672 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7673 /* Client can insist on breaking to none. */
7674 bool break_to_none = (oplocklevel == 0);
7675 bool result;
7677 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7678 "for fnum = %d\n", (unsigned int)oplocklevel,
7679 fsp->fnum ));
7682 * Make sure we have granted an exclusive or batch oplock on
7683 * this file.
7686 if (fsp->oplock_type == 0) {
7688 /* The Samba4 nbench simulator doesn't understand
7689 the difference between break to level2 and break
7690 to none from level2 - it sends oplock break
7691 replies in both cases. Don't keep logging an error
7692 message here - just ignore it. JRA. */
7694 DEBUG(5,("reply_lockingX: Error : oplock break from "
7695 "client for fnum = %d (oplock=%d) and no "
7696 "oplock granted on this file (%s).\n",
7697 fsp->fnum, fsp->oplock_type,
7698 fsp_str_dbg(fsp)));
7700 /* if this is a pure oplock break request then don't
7701 * send a reply */
7702 if (num_locks == 0 && num_ulocks == 0) {
7703 END_PROFILE(SMBlockingX);
7704 return;
7705 } else {
7706 END_PROFILE(SMBlockingX);
7707 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7708 return;
7712 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7713 (break_to_none)) {
7714 result = remove_oplock(fsp);
7715 } else {
7716 result = downgrade_oplock(fsp);
7719 if (!result) {
7720 DEBUG(0, ("reply_lockingX: error in removing "
7721 "oplock on file %s\n", fsp_str_dbg(fsp)));
7722 /* Hmmm. Is this panic justified? */
7723 smb_panic("internal tdb error");
7726 reply_to_oplock_break_requests(fsp);
7728 /* if this is a pure oplock break request then don't send a
7729 * reply */
7730 if (num_locks == 0 && num_ulocks == 0) {
7731 /* Sanity check - ensure a pure oplock break is not a
7732 chained request. */
7733 if(CVAL(req->vwv+0, 0) != 0xff)
7734 DEBUG(0,("reply_lockingX: Error : pure oplock "
7735 "break is a chained %d request !\n",
7736 (unsigned int)CVAL(req->vwv+0, 0)));
7737 END_PROFILE(SMBlockingX);
7738 return;
7742 if (req->buflen <
7743 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7744 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7745 END_PROFILE(SMBlockingX);
7746 return;
7749 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7750 if (ulocks == NULL) {
7751 reply_nterror(req, NT_STATUS_NO_MEMORY);
7752 END_PROFILE(SMBlockingX);
7753 return;
7756 locks = talloc_array(req, struct smbd_lock_element, num_locks);
7757 if (locks == NULL) {
7758 reply_nterror(req, NT_STATUS_NO_MEMORY);
7759 END_PROFILE(SMBlockingX);
7760 return;
7763 /* Data now points at the beginning of the list
7764 of smb_unlkrng structs */
7765 for(i = 0; i < (int)num_ulocks; i++) {
7766 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
7767 ulocks[i].count = get_lock_count(data, i, large_file_format);
7768 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7769 ulocks[i].brltype = UNLOCK_LOCK;
7772 * There is no error code marked "stupid client bug".... :-).
7774 if(err) {
7775 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7776 END_PROFILE(SMBlockingX);
7777 return;
7781 /* Now do any requested locks */
7782 data += ((large_file_format ? 20 : 10)*num_ulocks);
7784 /* Data now points at the beginning of the list
7785 of smb_lkrng structs */
7787 for(i = 0; i < (int)num_locks; i++) {
7788 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7789 locks[i].count = get_lock_count(data, i, large_file_format);
7790 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7792 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7793 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7794 locks[i].brltype = PENDING_READ_LOCK;
7795 } else {
7796 locks[i].brltype = READ_LOCK;
7798 } else {
7799 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7800 locks[i].brltype = PENDING_WRITE_LOCK;
7801 } else {
7802 locks[i].brltype = WRITE_LOCK;
7807 * There is no error code marked "stupid client bug".... :-).
7809 if(err) {
7810 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7811 END_PROFILE(SMBlockingX);
7812 return;
7816 status = smbd_do_locking(req, fsp,
7817 locktype, lock_timeout,
7818 num_ulocks, ulocks,
7819 num_locks, locks,
7820 &async);
7821 if (!NT_STATUS_IS_OK(status)) {
7822 END_PROFILE(SMBlockingX);
7823 reply_nterror(req, status);
7824 return;
7826 if (async) {
7827 END_PROFILE(SMBlockingX);
7828 return;
7831 reply_outbuf(req, 2, 0);
7833 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7834 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7836 END_PROFILE(SMBlockingX);
7837 chain_reply(req);
7840 #undef DBGC_CLASS
7841 #define DBGC_CLASS DBGC_ALL
7843 /****************************************************************************
7844 Reply to a SMBreadbmpx (read block multiplex) request.
7845 Always reply with an error, if someone has a platform really needs this,
7846 please contact vl@samba.org
7847 ****************************************************************************/
7849 void reply_readbmpx(struct smb_request *req)
7851 START_PROFILE(SMBreadBmpx);
7852 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7853 END_PROFILE(SMBreadBmpx);
7854 return;
7857 /****************************************************************************
7858 Reply to a SMBreadbs (read block multiplex secondary) request.
7859 Always reply with an error, if someone has a platform really needs this,
7860 please contact vl@samba.org
7861 ****************************************************************************/
7863 void reply_readbs(struct smb_request *req)
7865 START_PROFILE(SMBreadBs);
7866 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7867 END_PROFILE(SMBreadBs);
7868 return;
7871 /****************************************************************************
7872 Reply to a SMBsetattrE.
7873 ****************************************************************************/
7875 void reply_setattrE(struct smb_request *req)
7877 connection_struct *conn = req->conn;
7878 struct smb_file_time ft;
7879 files_struct *fsp;
7880 NTSTATUS status;
7882 START_PROFILE(SMBsetattrE);
7883 ZERO_STRUCT(ft);
7885 if (req->wct < 7) {
7886 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7887 goto out;
7890 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7892 if(!fsp || (fsp->conn != conn)) {
7893 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7894 goto out;
7898 * Convert the DOS times into unix times.
7901 ft.atime = convert_time_t_to_timespec(
7902 srv_make_unix_date2(req->vwv+3));
7903 ft.mtime = convert_time_t_to_timespec(
7904 srv_make_unix_date2(req->vwv+5));
7905 ft.create_time = convert_time_t_to_timespec(
7906 srv_make_unix_date2(req->vwv+1));
7908 reply_outbuf(req, 0, 0);
7911 * Patch from Ray Frush <frush@engr.colostate.edu>
7912 * Sometimes times are sent as zero - ignore them.
7915 /* Ensure we have a valid stat struct for the source. */
7916 status = vfs_stat_fsp(fsp);
7917 if (!NT_STATUS_IS_OK(status)) {
7918 reply_nterror(req, status);
7919 goto out;
7922 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7923 if (!NT_STATUS_IS_OK(status)) {
7924 reply_nterror(req, status);
7925 goto out;
7928 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7929 " createtime=%u\n",
7930 fsp->fnum,
7931 (unsigned int)ft.atime.tv_sec,
7932 (unsigned int)ft.mtime.tv_sec,
7933 (unsigned int)ft.create_time.tv_sec
7935 out:
7936 END_PROFILE(SMBsetattrE);
7937 return;
7941 /* Back from the dead for OS/2..... JRA. */
7943 /****************************************************************************
7944 Reply to a SMBwritebmpx (write block multiplex primary) request.
7945 Always reply with an error, if someone has a platform really needs this,
7946 please contact vl@samba.org
7947 ****************************************************************************/
7949 void reply_writebmpx(struct smb_request *req)
7951 START_PROFILE(SMBwriteBmpx);
7952 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7953 END_PROFILE(SMBwriteBmpx);
7954 return;
7957 /****************************************************************************
7958 Reply to a SMBwritebs (write block multiplex secondary) request.
7959 Always reply with an error, if someone has a platform really needs this,
7960 please contact vl@samba.org
7961 ****************************************************************************/
7963 void reply_writebs(struct smb_request *req)
7965 START_PROFILE(SMBwriteBs);
7966 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7967 END_PROFILE(SMBwriteBs);
7968 return;
7971 /****************************************************************************
7972 Reply to a SMBgetattrE.
7973 ****************************************************************************/
7975 void reply_getattrE(struct smb_request *req)
7977 connection_struct *conn = req->conn;
7978 int mode;
7979 files_struct *fsp;
7980 struct timespec create_ts;
7982 START_PROFILE(SMBgetattrE);
7984 if (req->wct < 1) {
7985 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7986 END_PROFILE(SMBgetattrE);
7987 return;
7990 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7992 if(!fsp || (fsp->conn != conn)) {
7993 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7994 END_PROFILE(SMBgetattrE);
7995 return;
7998 /* Do an fstat on this file */
7999 if(fsp_stat(fsp)) {
8000 reply_nterror(req, map_nt_error_from_unix(errno));
8001 END_PROFILE(SMBgetattrE);
8002 return;
8005 mode = dos_mode(conn, fsp->fsp_name);
8008 * Convert the times into dos times. Set create
8009 * date to be last modify date as UNIX doesn't save
8010 * this.
8013 reply_outbuf(req, 11, 0);
8015 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8016 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8017 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8018 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8019 /* Should we check pending modtime here ? JRA */
8020 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8021 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8023 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8024 SIVAL(req->outbuf, smb_vwv6, 0);
8025 SIVAL(req->outbuf, smb_vwv8, 0);
8026 } else {
8027 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8028 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
8029 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8031 SSVAL(req->outbuf,smb_vwv10, mode);
8033 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
8035 END_PROFILE(SMBgetattrE);
8036 return;