s3: We only need base_name in map_open_params_to_ntcreate
[Samba.git] / source3 / smbd / reply.c
blob4178f3f537c512118cff4ff9f6471edcc35fac79
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, &conn->session_info->utok)) {
2545 close_file(req, fsp, NORMAL_CLOSE);
2546 return NT_STATUS_ACCESS_DENIED;
2549 return close_file(req, fsp, NORMAL_CLOSE);
2552 /****************************************************************************
2553 The guts of the unlink command, split out so it may be called by the NT SMB
2554 code.
2555 ****************************************************************************/
2557 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2558 uint32 dirtype, struct smb_filename *smb_fname,
2559 bool has_wild)
2561 char *fname_dir = NULL;
2562 char *fname_mask = NULL;
2563 int count=0;
2564 NTSTATUS status = NT_STATUS_OK;
2565 TALLOC_CTX *ctx = talloc_tos();
2567 /* Split up the directory from the filename/mask. */
2568 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2569 &fname_dir, &fname_mask);
2570 if (!NT_STATUS_IS_OK(status)) {
2571 goto out;
2575 * We should only check the mangled cache
2576 * here if unix_convert failed. This means
2577 * that the path in 'mask' doesn't exist
2578 * on the file system and so we need to look
2579 * for a possible mangle. This patch from
2580 * Tine Smukavec <valentin.smukavec@hermes.si>.
2583 if (!VALID_STAT(smb_fname->st) &&
2584 mangle_is_mangled(fname_mask, conn->params)) {
2585 char *new_mask = NULL;
2586 mangle_lookup_name_from_8_3(ctx, fname_mask,
2587 &new_mask, conn->params);
2588 if (new_mask) {
2589 TALLOC_FREE(fname_mask);
2590 fname_mask = new_mask;
2594 if (!has_wild) {
2597 * Only one file needs to be unlinked. Append the mask back
2598 * onto the directory.
2600 TALLOC_FREE(smb_fname->base_name);
2601 if (ISDOT(fname_dir)) {
2602 /* Ensure we use canonical names on open. */
2603 smb_fname->base_name = talloc_asprintf(smb_fname,
2604 "%s",
2605 fname_mask);
2606 } else {
2607 smb_fname->base_name = talloc_asprintf(smb_fname,
2608 "%s/%s",
2609 fname_dir,
2610 fname_mask);
2612 if (!smb_fname->base_name) {
2613 status = NT_STATUS_NO_MEMORY;
2614 goto out;
2616 if (dirtype == 0) {
2617 dirtype = FILE_ATTRIBUTE_NORMAL;
2620 status = check_name(conn, smb_fname->base_name);
2621 if (!NT_STATUS_IS_OK(status)) {
2622 goto out;
2625 status = do_unlink(conn, req, smb_fname, dirtype);
2626 if (!NT_STATUS_IS_OK(status)) {
2627 goto out;
2630 count++;
2631 } else {
2632 struct smb_Dir *dir_hnd = NULL;
2633 long offset = 0;
2634 const char *dname = NULL;
2635 char *talloced = NULL;
2637 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
2638 status = NT_STATUS_OBJECT_NAME_INVALID;
2639 goto out;
2642 if (strequal(fname_mask,"????????.???")) {
2643 TALLOC_FREE(fname_mask);
2644 fname_mask = talloc_strdup(ctx, "*");
2645 if (!fname_mask) {
2646 status = NT_STATUS_NO_MEMORY;
2647 goto out;
2651 status = check_name(conn, fname_dir);
2652 if (!NT_STATUS_IS_OK(status)) {
2653 goto out;
2656 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2657 dirtype);
2658 if (dir_hnd == NULL) {
2659 status = map_nt_error_from_unix(errno);
2660 goto out;
2663 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2664 the pattern matches against the long name, otherwise the short name
2665 We don't implement this yet XXXX
2668 status = NT_STATUS_NO_SUCH_FILE;
2670 while ((dname = ReadDirName(dir_hnd, &offset,
2671 &smb_fname->st, &talloced))) {
2672 TALLOC_CTX *frame = talloc_stackframe();
2674 if (!is_visible_file(conn, fname_dir, dname,
2675 &smb_fname->st, true)) {
2676 TALLOC_FREE(frame);
2677 TALLOC_FREE(talloced);
2678 continue;
2681 /* Quick check for "." and ".." */
2682 if (ISDOT(dname) || ISDOTDOT(dname)) {
2683 TALLOC_FREE(frame);
2684 TALLOC_FREE(talloced);
2685 continue;
2688 if(!mask_match(dname, fname_mask,
2689 conn->case_sensitive)) {
2690 TALLOC_FREE(frame);
2691 TALLOC_FREE(talloced);
2692 continue;
2695 TALLOC_FREE(smb_fname->base_name);
2696 if (ISDOT(fname_dir)) {
2697 /* Ensure we use canonical names on open. */
2698 smb_fname->base_name =
2699 talloc_asprintf(smb_fname, "%s",
2700 dname);
2701 } else {
2702 smb_fname->base_name =
2703 talloc_asprintf(smb_fname, "%s/%s",
2704 fname_dir, dname);
2707 if (!smb_fname->base_name) {
2708 TALLOC_FREE(dir_hnd);
2709 status = NT_STATUS_NO_MEMORY;
2710 TALLOC_FREE(frame);
2711 TALLOC_FREE(talloced);
2712 goto out;
2715 status = check_name(conn, smb_fname->base_name);
2716 if (!NT_STATUS_IS_OK(status)) {
2717 TALLOC_FREE(dir_hnd);
2718 TALLOC_FREE(frame);
2719 TALLOC_FREE(talloced);
2720 goto out;
2723 status = do_unlink(conn, req, smb_fname, dirtype);
2724 if (!NT_STATUS_IS_OK(status)) {
2725 TALLOC_FREE(frame);
2726 TALLOC_FREE(talloced);
2727 continue;
2730 count++;
2731 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2732 smb_fname->base_name));
2734 TALLOC_FREE(frame);
2735 TALLOC_FREE(talloced);
2737 TALLOC_FREE(dir_hnd);
2740 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2741 status = map_nt_error_from_unix(errno);
2744 out:
2745 TALLOC_FREE(fname_dir);
2746 TALLOC_FREE(fname_mask);
2747 return status;
2750 /****************************************************************************
2751 Reply to a unlink
2752 ****************************************************************************/
2754 void reply_unlink(struct smb_request *req)
2756 connection_struct *conn = req->conn;
2757 char *name = NULL;
2758 struct smb_filename *smb_fname = NULL;
2759 uint32 dirtype;
2760 NTSTATUS status;
2761 bool path_contains_wcard = False;
2762 TALLOC_CTX *ctx = talloc_tos();
2764 START_PROFILE(SMBunlink);
2766 if (req->wct < 1) {
2767 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2768 goto out;
2771 dirtype = SVAL(req->vwv+0, 0);
2773 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2774 STR_TERMINATE, &status,
2775 &path_contains_wcard);
2776 if (!NT_STATUS_IS_OK(status)) {
2777 reply_nterror(req, status);
2778 goto out;
2781 status = filename_convert(ctx, conn,
2782 req->flags2 & FLAGS2_DFS_PATHNAMES,
2783 name,
2784 UCF_COND_ALLOW_WCARD_LCOMP,
2785 &path_contains_wcard,
2786 &smb_fname);
2787 if (!NT_STATUS_IS_OK(status)) {
2788 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2789 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2790 ERRSRV, ERRbadpath);
2791 goto out;
2793 reply_nterror(req, status);
2794 goto out;
2797 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2799 status = unlink_internals(conn, req, dirtype, smb_fname,
2800 path_contains_wcard);
2801 if (!NT_STATUS_IS_OK(status)) {
2802 if (open_was_deferred(req->mid)) {
2803 /* We have re-scheduled this call. */
2804 goto out;
2806 reply_nterror(req, status);
2807 goto out;
2810 reply_outbuf(req, 0, 0);
2811 out:
2812 TALLOC_FREE(smb_fname);
2813 END_PROFILE(SMBunlink);
2814 return;
2817 /****************************************************************************
2818 Fail for readbraw.
2819 ****************************************************************************/
2821 static void fail_readraw(void)
2823 const char *errstr = talloc_asprintf(talloc_tos(),
2824 "FAIL ! reply_readbraw: socket write fail (%s)",
2825 strerror(errno));
2826 if (!errstr) {
2827 errstr = "";
2829 exit_server_cleanly(errstr);
2832 /****************************************************************************
2833 Fake (read/write) sendfile. Returns -1 on read or write fail.
2834 ****************************************************************************/
2836 ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread)
2838 size_t bufsize;
2839 size_t tosend = nread;
2840 char *buf;
2842 if (nread == 0) {
2843 return 0;
2846 bufsize = MIN(nread, 65536);
2848 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2849 return -1;
2852 while (tosend > 0) {
2853 ssize_t ret;
2854 size_t cur_read;
2856 if (tosend > bufsize) {
2857 cur_read = bufsize;
2858 } else {
2859 cur_read = tosend;
2861 ret = read_file(fsp,buf,startpos,cur_read);
2862 if (ret == -1) {
2863 SAFE_FREE(buf);
2864 return -1;
2867 /* If we had a short read, fill with zeros. */
2868 if (ret < cur_read) {
2869 memset(buf + ret, '\0', cur_read - ret);
2872 if (write_data(fsp->conn->sconn->sock, buf, cur_read)
2873 != cur_read) {
2874 char addr[INET6_ADDRSTRLEN];
2876 * Try and give an error message saying what
2877 * client failed.
2879 DEBUG(0, ("write_data failed for client %s. "
2880 "Error %s\n",
2881 get_peer_addr(fsp->conn->sconn->sock, addr,
2882 sizeof(addr)),
2883 strerror(errno)));
2884 SAFE_FREE(buf);
2885 return -1;
2887 tosend -= cur_read;
2888 startpos += cur_read;
2891 SAFE_FREE(buf);
2892 return (ssize_t)nread;
2895 /****************************************************************************
2896 Deal with the case of sendfile reading less bytes from the file than
2897 requested. Fill with zeros (all we can do).
2898 ****************************************************************************/
2900 void sendfile_short_send(files_struct *fsp,
2901 ssize_t nread,
2902 size_t headersize,
2903 size_t smb_maxcnt)
2905 #define SHORT_SEND_BUFSIZE 1024
2906 if (nread < headersize) {
2907 DEBUG(0,("sendfile_short_send: sendfile failed to send "
2908 "header for file %s (%s). Terminating\n",
2909 fsp_str_dbg(fsp), strerror(errno)));
2910 exit_server_cleanly("sendfile_short_send failed");
2913 nread -= headersize;
2915 if (nread < smb_maxcnt) {
2916 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2917 if (!buf) {
2918 exit_server_cleanly("sendfile_short_send: "
2919 "malloc failed");
2922 DEBUG(0,("sendfile_short_send: filling truncated file %s "
2923 "with zeros !\n", fsp_str_dbg(fsp)));
2925 while (nread < smb_maxcnt) {
2927 * We asked for the real file size and told sendfile
2928 * to not go beyond the end of the file. But it can
2929 * happen that in between our fstat call and the
2930 * sendfile call the file was truncated. This is very
2931 * bad because we have already announced the larger
2932 * number of bytes to the client.
2934 * The best we can do now is to send 0-bytes, just as
2935 * a read from a hole in a sparse file would do.
2937 * This should happen rarely enough that I don't care
2938 * about efficiency here :-)
2940 size_t to_write;
2942 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2943 if (write_data(fsp->conn->sconn->sock, buf, to_write)
2944 != to_write) {
2945 char addr[INET6_ADDRSTRLEN];
2947 * Try and give an error message saying what
2948 * client failed.
2950 DEBUG(0, ("write_data failed for client %s. "
2951 "Error %s\n",
2952 get_peer_addr(
2953 fsp->conn->sconn->sock, addr,
2954 sizeof(addr)),
2955 strerror(errno)));
2956 exit_server_cleanly("sendfile_short_send: "
2957 "write_data failed");
2959 nread += to_write;
2961 SAFE_FREE(buf);
2965 /****************************************************************************
2966 Return a readbraw error (4 bytes of zero).
2967 ****************************************************************************/
2969 static void reply_readbraw_error(struct smbd_server_connection *sconn)
2971 char header[4];
2973 SIVAL(header,0,0);
2975 smbd_lock_socket(sconn);
2976 if (write_data(sconn->sock,header,4) != 4) {
2977 char addr[INET6_ADDRSTRLEN];
2979 * Try and give an error message saying what
2980 * client failed.
2982 DEBUG(0, ("write_data failed for client %s. "
2983 "Error %s\n",
2984 get_peer_addr(sconn->sock, addr, sizeof(addr)),
2985 strerror(errno)));
2987 fail_readraw();
2989 smbd_unlock_socket(sconn);
2992 /****************************************************************************
2993 Use sendfile in readbraw.
2994 ****************************************************************************/
2996 static void send_file_readbraw(connection_struct *conn,
2997 struct smb_request *req,
2998 files_struct *fsp,
2999 SMB_OFF_T startpos,
3000 size_t nread,
3001 ssize_t mincount)
3003 struct smbd_server_connection *sconn = req->sconn;
3004 char *outbuf = NULL;
3005 ssize_t ret=0;
3008 * We can only use sendfile on a non-chained packet
3009 * but we can use on a non-oplocked file. tridge proved this
3010 * on a train in Germany :-). JRA.
3011 * reply_readbraw has already checked the length.
3014 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3015 (fsp->wcp == NULL) &&
3016 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3017 ssize_t sendfile_read = -1;
3018 char header[4];
3019 DATA_BLOB header_blob;
3021 _smb_setlen(header,nread);
3022 header_blob = data_blob_const(header, 4);
3024 sendfile_read = SMB_VFS_SENDFILE(sconn->sock, fsp,
3025 &header_blob, startpos,
3026 nread);
3027 if (sendfile_read == -1) {
3028 /* Returning ENOSYS means no data at all was sent.
3029 * Do this as a normal read. */
3030 if (errno == ENOSYS) {
3031 goto normal_readbraw;
3035 * Special hack for broken Linux with no working sendfile. If we
3036 * return EINTR we sent the header but not the rest of the data.
3037 * Fake this up by doing read/write calls.
3039 if (errno == EINTR) {
3040 /* Ensure we don't do this again. */
3041 set_use_sendfile(SNUM(conn), False);
3042 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3044 if (fake_sendfile(fsp, startpos, nread) == -1) {
3045 DEBUG(0,("send_file_readbraw: "
3046 "fake_sendfile failed for "
3047 "file %s (%s).\n",
3048 fsp_str_dbg(fsp),
3049 strerror(errno)));
3050 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3052 return;
3055 DEBUG(0,("send_file_readbraw: sendfile failed for "
3056 "file %s (%s). Terminating\n",
3057 fsp_str_dbg(fsp), strerror(errno)));
3058 exit_server_cleanly("send_file_readbraw sendfile failed");
3059 } else if (sendfile_read == 0) {
3061 * Some sendfile implementations return 0 to indicate
3062 * that there was a short read, but nothing was
3063 * actually written to the socket. In this case,
3064 * fallback to the normal read path so the header gets
3065 * the correct byte count.
3067 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3068 "bytes falling back to the normal read: "
3069 "%s\n", fsp_str_dbg(fsp)));
3070 goto normal_readbraw;
3073 /* Deal with possible short send. */
3074 if (sendfile_read != 4+nread) {
3075 sendfile_short_send(fsp, sendfile_read, 4, nread);
3077 return;
3080 normal_readbraw:
3082 outbuf = TALLOC_ARRAY(NULL, char, nread+4);
3083 if (!outbuf) {
3084 DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
3085 (unsigned)(nread+4)));
3086 reply_readbraw_error(sconn);
3087 return;
3090 if (nread > 0) {
3091 ret = read_file(fsp,outbuf+4,startpos,nread);
3092 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3093 if (ret < mincount)
3094 ret = 0;
3095 #else
3096 if (ret < nread)
3097 ret = 0;
3098 #endif
3101 _smb_setlen(outbuf,ret);
3102 if (write_data(sconn->sock, outbuf, 4+ret) != 4+ret) {
3103 char addr[INET6_ADDRSTRLEN];
3105 * Try and give an error message saying what
3106 * client failed.
3108 DEBUG(0, ("write_data failed for client %s. "
3109 "Error %s\n",
3110 get_peer_addr(fsp->conn->sconn->sock, addr,
3111 sizeof(addr)),
3112 strerror(errno)));
3114 fail_readraw();
3117 TALLOC_FREE(outbuf);
3120 /****************************************************************************
3121 Reply to a readbraw (core+ protocol).
3122 ****************************************************************************/
3124 void reply_readbraw(struct smb_request *req)
3126 connection_struct *conn = req->conn;
3127 struct smbd_server_connection *sconn = req->sconn;
3128 ssize_t maxcount,mincount;
3129 size_t nread = 0;
3130 SMB_OFF_T startpos;
3131 files_struct *fsp;
3132 struct lock_struct lock;
3133 SMB_OFF_T size = 0;
3135 START_PROFILE(SMBreadbraw);
3137 if (srv_is_signing_active(sconn) ||
3138 is_encrypted_packet(req->inbuf)) {
3139 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3140 "raw reads/writes are disallowed.");
3143 if (req->wct < 8) {
3144 reply_readbraw_error(sconn);
3145 END_PROFILE(SMBreadbraw);
3146 return;
3149 if (sconn->smb1.echo_handler.trusted_fde) {
3150 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3151 "'async smb echo handler = yes'\n"));
3152 reply_readbraw_error(sconn);
3153 END_PROFILE(SMBreadbraw);
3154 return;
3158 * Special check if an oplock break has been issued
3159 * and the readraw request croses on the wire, we must
3160 * return a zero length response here.
3163 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3166 * We have to do a check_fsp by hand here, as
3167 * we must always return 4 zero bytes on error,
3168 * not a NTSTATUS.
3171 if (!fsp || !conn || conn != fsp->conn ||
3172 req->vuid != fsp->vuid ||
3173 fsp->is_directory || fsp->fh->fd == -1) {
3175 * fsp could be NULL here so use the value from the packet. JRA.
3177 DEBUG(3,("reply_readbraw: fnum %d not valid "
3178 "- cache prime?\n",
3179 (int)SVAL(req->vwv+0, 0)));
3180 reply_readbraw_error(sconn);
3181 END_PROFILE(SMBreadbraw);
3182 return;
3185 /* Do a "by hand" version of CHECK_READ. */
3186 if (!(fsp->can_read ||
3187 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3188 (fsp->access_mask & FILE_EXECUTE)))) {
3189 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3190 (int)SVAL(req->vwv+0, 0)));
3191 reply_readbraw_error(sconn);
3192 END_PROFILE(SMBreadbraw);
3193 return;
3196 flush_write_cache(fsp, READRAW_FLUSH);
3198 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3199 if(req->wct == 10) {
3201 * This is a large offset (64 bit) read.
3203 #ifdef LARGE_SMB_OFF_T
3205 startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3207 #else /* !LARGE_SMB_OFF_T */
3210 * Ensure we haven't been sent a >32 bit offset.
3213 if(IVAL(req->vwv+8, 0) != 0) {
3214 DEBUG(0,("reply_readbraw: large offset "
3215 "(%x << 32) used and we don't support "
3216 "64 bit offsets.\n",
3217 (unsigned int)IVAL(req->vwv+8, 0) ));
3218 reply_readbraw_error(sconn);
3219 END_PROFILE(SMBreadbraw);
3220 return;
3223 #endif /* LARGE_SMB_OFF_T */
3225 if(startpos < 0) {
3226 DEBUG(0,("reply_readbraw: negative 64 bit "
3227 "readraw offset (%.0f) !\n",
3228 (double)startpos ));
3229 reply_readbraw_error(sconn);
3230 END_PROFILE(SMBreadbraw);
3231 return;
3235 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3236 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3238 /* ensure we don't overrun the packet size */
3239 maxcount = MIN(65535,maxcount);
3241 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3242 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3243 &lock);
3245 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3246 reply_readbraw_error(sconn);
3247 END_PROFILE(SMBreadbraw);
3248 return;
3251 if (fsp_stat(fsp) == 0) {
3252 size = fsp->fsp_name->st.st_ex_size;
3255 if (startpos >= size) {
3256 nread = 0;
3257 } else {
3258 nread = MIN(maxcount,(size - startpos));
3261 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3262 if (nread < mincount)
3263 nread = 0;
3264 #endif
3266 DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3267 "min=%lu nread=%lu\n",
3268 fsp->fnum, (double)startpos,
3269 (unsigned long)maxcount,
3270 (unsigned long)mincount,
3271 (unsigned long)nread ) );
3273 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3275 DEBUG(5,("reply_readbraw finished\n"));
3277 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3279 END_PROFILE(SMBreadbraw);
3280 return;
3283 #undef DBGC_CLASS
3284 #define DBGC_CLASS DBGC_LOCKING
3286 /****************************************************************************
3287 Reply to a lockread (core+ protocol).
3288 ****************************************************************************/
3290 void reply_lockread(struct smb_request *req)
3292 connection_struct *conn = req->conn;
3293 ssize_t nread = -1;
3294 char *data;
3295 SMB_OFF_T startpos;
3296 size_t numtoread;
3297 NTSTATUS status;
3298 files_struct *fsp;
3299 struct byte_range_lock *br_lck = NULL;
3300 char *p = NULL;
3301 struct smbd_server_connection *sconn = req->sconn;
3303 START_PROFILE(SMBlockread);
3305 if (req->wct < 5) {
3306 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3307 END_PROFILE(SMBlockread);
3308 return;
3311 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3313 if (!check_fsp(conn, req, fsp)) {
3314 END_PROFILE(SMBlockread);
3315 return;
3318 if (!CHECK_READ(fsp,req)) {
3319 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3320 END_PROFILE(SMBlockread);
3321 return;
3324 numtoread = SVAL(req->vwv+1, 0);
3325 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3327 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3329 reply_outbuf(req, 5, numtoread + 3);
3331 data = smb_buf(req->outbuf) + 3;
3334 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3335 * protocol request that predates the read/write lock concept.
3336 * Thus instead of asking for a read lock here we need to ask
3337 * for a write lock. JRA.
3338 * Note that the requested lock size is unaffected by max_recv.
3341 br_lck = do_lock(req->sconn->msg_ctx,
3342 fsp,
3343 (uint64_t)req->smbpid,
3344 (uint64_t)numtoread,
3345 (uint64_t)startpos,
3346 WRITE_LOCK,
3347 WINDOWS_LOCK,
3348 False, /* Non-blocking lock. */
3349 &status,
3350 NULL,
3351 NULL);
3352 TALLOC_FREE(br_lck);
3354 if (NT_STATUS_V(status)) {
3355 reply_nterror(req, status);
3356 END_PROFILE(SMBlockread);
3357 return;
3361 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3364 if (numtoread > sconn->smb1.negprot.max_recv) {
3365 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3366 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3367 (unsigned int)numtoread,
3368 (unsigned int)sconn->smb1.negprot.max_recv));
3369 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3371 nread = read_file(fsp,data,startpos,numtoread);
3373 if (nread < 0) {
3374 reply_nterror(req, map_nt_error_from_unix(errno));
3375 END_PROFILE(SMBlockread);
3376 return;
3379 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3381 SSVAL(req->outbuf,smb_vwv0,nread);
3382 SSVAL(req->outbuf,smb_vwv5,nread+3);
3383 p = smb_buf(req->outbuf);
3384 SCVAL(p,0,0); /* pad byte. */
3385 SSVAL(p,1,nread);
3387 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3388 fsp->fnum, (int)numtoread, (int)nread));
3390 END_PROFILE(SMBlockread);
3391 return;
3394 #undef DBGC_CLASS
3395 #define DBGC_CLASS DBGC_ALL
3397 /****************************************************************************
3398 Reply to a read.
3399 ****************************************************************************/
3401 void reply_read(struct smb_request *req)
3403 connection_struct *conn = req->conn;
3404 size_t numtoread;
3405 ssize_t nread = 0;
3406 char *data;
3407 SMB_OFF_T startpos;
3408 int outsize = 0;
3409 files_struct *fsp;
3410 struct lock_struct lock;
3411 struct smbd_server_connection *sconn = req->sconn;
3413 START_PROFILE(SMBread);
3415 if (req->wct < 3) {
3416 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3417 END_PROFILE(SMBread);
3418 return;
3421 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3423 if (!check_fsp(conn, req, fsp)) {
3424 END_PROFILE(SMBread);
3425 return;
3428 if (!CHECK_READ(fsp,req)) {
3429 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3430 END_PROFILE(SMBread);
3431 return;
3434 numtoread = SVAL(req->vwv+1, 0);
3435 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3437 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3440 * The requested read size cannot be greater than max_recv. JRA.
3442 if (numtoread > sconn->smb1.negprot.max_recv) {
3443 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3444 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3445 (unsigned int)numtoread,
3446 (unsigned int)sconn->smb1.negprot.max_recv));
3447 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3450 reply_outbuf(req, 5, numtoread+3);
3452 data = smb_buf(req->outbuf) + 3;
3454 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3455 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3456 &lock);
3458 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3459 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3460 END_PROFILE(SMBread);
3461 return;
3464 if (numtoread > 0)
3465 nread = read_file(fsp,data,startpos,numtoread);
3467 if (nread < 0) {
3468 reply_nterror(req, map_nt_error_from_unix(errno));
3469 goto strict_unlock;
3472 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3474 SSVAL(req->outbuf,smb_vwv0,nread);
3475 SSVAL(req->outbuf,smb_vwv5,nread+3);
3476 SCVAL(smb_buf(req->outbuf),0,1);
3477 SSVAL(smb_buf(req->outbuf),1,nread);
3479 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3480 fsp->fnum, (int)numtoread, (int)nread ) );
3482 strict_unlock:
3483 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3485 END_PROFILE(SMBread);
3486 return;
3489 /****************************************************************************
3490 Setup readX header.
3491 ****************************************************************************/
3493 static int setup_readX_header(struct smb_request *req, char *outbuf,
3494 size_t smb_maxcnt)
3496 int outsize;
3497 char *data;
3499 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3500 data = smb_buf(outbuf);
3502 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3504 SCVAL(outbuf,smb_vwv0,0xFF);
3505 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3506 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3507 SSVAL(outbuf,smb_vwv6,
3508 req_wct_ofs(req)
3509 + 1 /* the wct field */
3510 + 12 * sizeof(uint16_t) /* vwv */
3511 + 2); /* the buflen field */
3512 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3513 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3514 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3515 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3516 return outsize;
3519 /****************************************************************************
3520 Reply to a read and X - possibly using sendfile.
3521 ****************************************************************************/
3523 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3524 files_struct *fsp, SMB_OFF_T startpos,
3525 size_t smb_maxcnt)
3527 ssize_t nread = -1;
3528 struct lock_struct lock;
3529 int saved_errno = 0;
3531 if(fsp_stat(fsp) == -1) {
3532 reply_nterror(req, map_nt_error_from_unix(errno));
3533 return;
3536 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3537 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3538 &lock);
3540 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3541 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3542 return;
3545 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3546 (startpos > fsp->fsp_name->st.st_ex_size)
3547 || (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3549 * We already know that we would do a short read, so don't
3550 * try the sendfile() path.
3552 goto nosendfile_read;
3556 * We can only use sendfile on a non-chained packet
3557 * but we can use on a non-oplocked file. tridge proved this
3558 * on a train in Germany :-). JRA.
3561 if (!req_is_in_chain(req) &&
3562 !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3563 (fsp->wcp == NULL) &&
3564 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3565 uint8 headerbuf[smb_size + 12 * 2];
3566 DATA_BLOB header;
3569 * Set up the packet header before send. We
3570 * assume here the sendfile will work (get the
3571 * correct amount of data).
3574 header = data_blob_const(headerbuf, sizeof(headerbuf));
3576 construct_reply_common_req(req, (char *)headerbuf);
3577 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3579 nread = SMB_VFS_SENDFILE(req->sconn->sock, fsp, &header,
3580 startpos, smb_maxcnt);
3581 if (nread == -1) {
3582 /* Returning ENOSYS means no data at all was sent.
3583 Do this as a normal read. */
3584 if (errno == ENOSYS) {
3585 goto normal_read;
3589 * Special hack for broken Linux with no working sendfile. If we
3590 * return EINTR we sent the header but not the rest of the data.
3591 * Fake this up by doing read/write calls.
3594 if (errno == EINTR) {
3595 /* Ensure we don't do this again. */
3596 set_use_sendfile(SNUM(conn), False);
3597 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3598 nread = fake_sendfile(fsp, startpos,
3599 smb_maxcnt);
3600 if (nread == -1) {
3601 DEBUG(0,("send_file_readX: "
3602 "fake_sendfile failed for "
3603 "file %s (%s).\n",
3604 fsp_str_dbg(fsp),
3605 strerror(errno)));
3606 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3608 DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3609 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3610 /* No outbuf here means successful sendfile. */
3611 goto strict_unlock;
3614 DEBUG(0,("send_file_readX: sendfile failed for file "
3615 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3616 strerror(errno)));
3617 exit_server_cleanly("send_file_readX sendfile failed");
3618 } else if (nread == 0) {
3620 * Some sendfile implementations return 0 to indicate
3621 * that there was a short read, but nothing was
3622 * actually written to the socket. In this case,
3623 * fallback to the normal read path so the header gets
3624 * the correct byte count.
3626 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3627 "falling back to the normal read: %s\n",
3628 fsp_str_dbg(fsp)));
3629 goto normal_read;
3632 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3633 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3635 /* Deal with possible short send. */
3636 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3637 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3639 /* No outbuf here means successful sendfile. */
3640 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3641 SMB_PERFCOUNT_END(&req->pcd);
3642 goto strict_unlock;
3645 normal_read:
3647 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3648 uint8 headerbuf[smb_size + 2*12];
3650 construct_reply_common_req(req, (char *)headerbuf);
3651 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3653 /* Send out the header. */
3654 if (write_data(req->sconn->sock, (char *)headerbuf,
3655 sizeof(headerbuf)) != sizeof(headerbuf)) {
3657 char addr[INET6_ADDRSTRLEN];
3659 * Try and give an error message saying what
3660 * client failed.
3662 DEBUG(0, ("write_data failed for client %s. "
3663 "Error %s\n",
3664 get_peer_addr(req->sconn->sock, addr,
3665 sizeof(addr)),
3666 strerror(errno)));
3668 DEBUG(0,("send_file_readX: write_data failed for file "
3669 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3670 strerror(errno)));
3671 exit_server_cleanly("send_file_readX sendfile failed");
3673 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3674 if (nread == -1) {
3675 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3676 "file %s (%s).\n", fsp_str_dbg(fsp),
3677 strerror(errno)));
3678 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3680 goto strict_unlock;
3683 nosendfile_read:
3685 reply_outbuf(req, 12, smb_maxcnt);
3687 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3688 saved_errno = errno;
3690 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3692 if (nread < 0) {
3693 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3694 return;
3697 setup_readX_header(req, (char *)req->outbuf, nread);
3699 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3700 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3702 chain_reply(req);
3703 return;
3705 strict_unlock:
3706 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3707 TALLOC_FREE(req->outbuf);
3708 return;
3711 /****************************************************************************
3712 Reply to a read and X.
3713 ****************************************************************************/
3715 void reply_read_and_X(struct smb_request *req)
3717 connection_struct *conn = req->conn;
3718 files_struct *fsp;
3719 SMB_OFF_T startpos;
3720 size_t smb_maxcnt;
3721 bool big_readX = False;
3722 #if 0
3723 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3724 #endif
3726 START_PROFILE(SMBreadX);
3728 if ((req->wct != 10) && (req->wct != 12)) {
3729 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3730 return;
3733 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3734 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3735 smb_maxcnt = SVAL(req->vwv+5, 0);
3737 /* If it's an IPC, pass off the pipe handler. */
3738 if (IS_IPC(conn)) {
3739 reply_pipe_read_and_X(req);
3740 END_PROFILE(SMBreadX);
3741 return;
3744 if (!check_fsp(conn, req, fsp)) {
3745 END_PROFILE(SMBreadX);
3746 return;
3749 if (!CHECK_READ(fsp,req)) {
3750 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3751 END_PROFILE(SMBreadX);
3752 return;
3755 if (global_client_caps & CAP_LARGE_READX) {
3756 size_t upper_size = SVAL(req->vwv+7, 0);
3757 smb_maxcnt |= (upper_size<<16);
3758 if (upper_size > 1) {
3759 /* Can't do this on a chained packet. */
3760 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3761 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3762 END_PROFILE(SMBreadX);
3763 return;
3765 /* We currently don't do this on signed or sealed data. */
3766 if (srv_is_signing_active(req->sconn) ||
3767 is_encrypted_packet(req->inbuf)) {
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 if (nwritten < (ssize_t)numtowrite) {
4634 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4635 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4638 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4639 fsp->fnum, (int)numtowrite, (int)nwritten));
4641 status = sync_file(conn, fsp, write_through);
4642 if (!NT_STATUS_IS_OK(status)) {
4643 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4644 fsp_str_dbg(fsp), nt_errstr(status)));
4645 reply_nterror(req, status);
4646 goto out;
4649 END_PROFILE(SMBwriteX);
4650 chain_reply(req);
4651 return;
4653 out:
4654 END_PROFILE(SMBwriteX);
4655 return;
4658 /****************************************************************************
4659 Reply to a lseek.
4660 ****************************************************************************/
4662 void reply_lseek(struct smb_request *req)
4664 connection_struct *conn = req->conn;
4665 SMB_OFF_T startpos;
4666 SMB_OFF_T res= -1;
4667 int mode,umode;
4668 files_struct *fsp;
4670 START_PROFILE(SMBlseek);
4672 if (req->wct < 4) {
4673 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4674 END_PROFILE(SMBlseek);
4675 return;
4678 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4680 if (!check_fsp(conn, req, fsp)) {
4681 return;
4684 flush_write_cache(fsp, SEEK_FLUSH);
4686 mode = SVAL(req->vwv+1, 0) & 3;
4687 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4688 startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4690 switch (mode) {
4691 case 0:
4692 umode = SEEK_SET;
4693 res = startpos;
4694 break;
4695 case 1:
4696 umode = SEEK_CUR;
4697 res = fsp->fh->pos + startpos;
4698 break;
4699 case 2:
4700 umode = SEEK_END;
4701 break;
4702 default:
4703 umode = SEEK_SET;
4704 res = startpos;
4705 break;
4708 if (umode == SEEK_END) {
4709 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4710 if(errno == EINVAL) {
4711 SMB_OFF_T current_pos = startpos;
4713 if(fsp_stat(fsp) == -1) {
4714 reply_nterror(req,
4715 map_nt_error_from_unix(errno));
4716 END_PROFILE(SMBlseek);
4717 return;
4720 current_pos += fsp->fsp_name->st.st_ex_size;
4721 if(current_pos < 0)
4722 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4726 if(res == -1) {
4727 reply_nterror(req, map_nt_error_from_unix(errno));
4728 END_PROFILE(SMBlseek);
4729 return;
4733 fsp->fh->pos = res;
4735 reply_outbuf(req, 2, 0);
4736 SIVAL(req->outbuf,smb_vwv0,res);
4738 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4739 fsp->fnum, (double)startpos, (double)res, mode));
4741 END_PROFILE(SMBlseek);
4742 return;
4745 /****************************************************************************
4746 Reply to a flush.
4747 ****************************************************************************/
4749 void reply_flush(struct smb_request *req)
4751 connection_struct *conn = req->conn;
4752 uint16 fnum;
4753 files_struct *fsp;
4755 START_PROFILE(SMBflush);
4757 if (req->wct < 1) {
4758 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4759 return;
4762 fnum = SVAL(req->vwv+0, 0);
4763 fsp = file_fsp(req, fnum);
4765 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4766 return;
4769 if (!fsp) {
4770 file_sync_all(conn);
4771 } else {
4772 NTSTATUS status = sync_file(conn, fsp, True);
4773 if (!NT_STATUS_IS_OK(status)) {
4774 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4775 fsp_str_dbg(fsp), nt_errstr(status)));
4776 reply_nterror(req, status);
4777 END_PROFILE(SMBflush);
4778 return;
4782 reply_outbuf(req, 0, 0);
4784 DEBUG(3,("flush\n"));
4785 END_PROFILE(SMBflush);
4786 return;
4789 /****************************************************************************
4790 Reply to a exit.
4791 conn POINTER CAN BE NULL HERE !
4792 ****************************************************************************/
4794 void reply_exit(struct smb_request *req)
4796 START_PROFILE(SMBexit);
4798 file_close_pid(req->sconn, req->smbpid, req->vuid);
4800 reply_outbuf(req, 0, 0);
4802 DEBUG(3,("exit\n"));
4804 END_PROFILE(SMBexit);
4805 return;
4808 /****************************************************************************
4809 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4810 ****************************************************************************/
4812 void reply_close(struct smb_request *req)
4814 connection_struct *conn = req->conn;
4815 NTSTATUS status = NT_STATUS_OK;
4816 files_struct *fsp = NULL;
4817 START_PROFILE(SMBclose);
4819 if (req->wct < 3) {
4820 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4821 END_PROFILE(SMBclose);
4822 return;
4825 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4828 * We can only use check_fsp if we know it's not a directory.
4831 if (!check_fsp_open(conn, req, fsp)) {
4832 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4833 END_PROFILE(SMBclose);
4834 return;
4837 if(fsp->is_directory) {
4839 * Special case - close NT SMB directory handle.
4841 DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4842 status = close_file(req, fsp, NORMAL_CLOSE);
4843 } else {
4844 time_t t;
4846 * Close ordinary file.
4849 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4850 fsp->fh->fd, fsp->fnum,
4851 conn->num_files_open));
4854 * Take care of any time sent in the close.
4857 t = srv_make_unix_date3(req->vwv+1);
4858 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4861 * close_file() returns the unix errno if an error
4862 * was detected on close - normally this is due to
4863 * a disk full error. If not then it was probably an I/O error.
4866 status = close_file(req, fsp, NORMAL_CLOSE);
4869 if (!NT_STATUS_IS_OK(status)) {
4870 reply_nterror(req, status);
4871 END_PROFILE(SMBclose);
4872 return;
4875 reply_outbuf(req, 0, 0);
4876 END_PROFILE(SMBclose);
4877 return;
4880 /****************************************************************************
4881 Reply to a writeclose (Core+ protocol).
4882 ****************************************************************************/
4884 void reply_writeclose(struct smb_request *req)
4886 connection_struct *conn = req->conn;
4887 size_t numtowrite;
4888 ssize_t nwritten = -1;
4889 NTSTATUS close_status = NT_STATUS_OK;
4890 SMB_OFF_T startpos;
4891 const char *data;
4892 struct timespec mtime;
4893 files_struct *fsp;
4894 struct lock_struct lock;
4896 START_PROFILE(SMBwriteclose);
4898 if (req->wct < 6) {
4899 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4900 END_PROFILE(SMBwriteclose);
4901 return;
4904 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4906 if (!check_fsp(conn, req, fsp)) {
4907 END_PROFILE(SMBwriteclose);
4908 return;
4910 if (!CHECK_WRITE(fsp)) {
4911 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4912 END_PROFILE(SMBwriteclose);
4913 return;
4916 numtowrite = SVAL(req->vwv+1, 0);
4917 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4918 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4919 data = (const char *)req->buf + 1;
4921 if (!fsp->print_file) {
4922 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4923 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4924 &lock);
4926 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4927 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4928 END_PROFILE(SMBwriteclose);
4929 return;
4933 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4935 set_close_write_time(fsp, mtime);
4938 * More insanity. W2K only closes the file if writelen > 0.
4939 * JRA.
4942 if (numtowrite) {
4943 DEBUG(3,("reply_writeclose: zero length write doesn't close "
4944 "file %s\n", fsp_str_dbg(fsp)));
4945 close_status = close_file(req, fsp, NORMAL_CLOSE);
4948 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4949 fsp->fnum, (int)numtowrite, (int)nwritten,
4950 conn->num_files_open));
4952 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4953 reply_nterror(req, NT_STATUS_DISK_FULL);
4954 goto strict_unlock;
4957 if(!NT_STATUS_IS_OK(close_status)) {
4958 reply_nterror(req, close_status);
4959 goto strict_unlock;
4962 reply_outbuf(req, 1, 0);
4964 SSVAL(req->outbuf,smb_vwv0,nwritten);
4966 strict_unlock:
4967 if (numtowrite && !fsp->print_file) {
4968 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4971 END_PROFILE(SMBwriteclose);
4972 return;
4975 #undef DBGC_CLASS
4976 #define DBGC_CLASS DBGC_LOCKING
4978 /****************************************************************************
4979 Reply to a lock.
4980 ****************************************************************************/
4982 void reply_lock(struct smb_request *req)
4984 connection_struct *conn = req->conn;
4985 uint64_t count,offset;
4986 NTSTATUS status;
4987 files_struct *fsp;
4988 struct byte_range_lock *br_lck = NULL;
4990 START_PROFILE(SMBlock);
4992 if (req->wct < 5) {
4993 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4994 END_PROFILE(SMBlock);
4995 return;
4998 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5000 if (!check_fsp(conn, req, fsp)) {
5001 END_PROFILE(SMBlock);
5002 return;
5005 count = (uint64_t)IVAL(req->vwv+1, 0);
5006 offset = (uint64_t)IVAL(req->vwv+3, 0);
5008 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5009 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
5011 br_lck = do_lock(req->sconn->msg_ctx,
5012 fsp,
5013 (uint64_t)req->smbpid,
5014 count,
5015 offset,
5016 WRITE_LOCK,
5017 WINDOWS_LOCK,
5018 False, /* Non-blocking lock. */
5019 &status,
5020 NULL,
5021 NULL);
5023 TALLOC_FREE(br_lck);
5025 if (NT_STATUS_V(status)) {
5026 reply_nterror(req, status);
5027 END_PROFILE(SMBlock);
5028 return;
5031 reply_outbuf(req, 0, 0);
5033 END_PROFILE(SMBlock);
5034 return;
5037 /****************************************************************************
5038 Reply to a unlock.
5039 ****************************************************************************/
5041 void reply_unlock(struct smb_request *req)
5043 connection_struct *conn = req->conn;
5044 uint64_t count,offset;
5045 NTSTATUS status;
5046 files_struct *fsp;
5048 START_PROFILE(SMBunlock);
5050 if (req->wct < 5) {
5051 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5052 END_PROFILE(SMBunlock);
5053 return;
5056 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5058 if (!check_fsp(conn, req, fsp)) {
5059 END_PROFILE(SMBunlock);
5060 return;
5063 count = (uint64_t)IVAL(req->vwv+1, 0);
5064 offset = (uint64_t)IVAL(req->vwv+3, 0);
5066 status = do_unlock(req->sconn->msg_ctx,
5067 fsp,
5068 (uint64_t)req->smbpid,
5069 count,
5070 offset,
5071 WINDOWS_LOCK);
5073 if (NT_STATUS_V(status)) {
5074 reply_nterror(req, status);
5075 END_PROFILE(SMBunlock);
5076 return;
5079 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
5080 fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
5082 reply_outbuf(req, 0, 0);
5084 END_PROFILE(SMBunlock);
5085 return;
5088 #undef DBGC_CLASS
5089 #define DBGC_CLASS DBGC_ALL
5091 /****************************************************************************
5092 Reply to a tdis.
5093 conn POINTER CAN BE NULL HERE !
5094 ****************************************************************************/
5096 void reply_tdis(struct smb_request *req)
5098 connection_struct *conn = req->conn;
5099 START_PROFILE(SMBtdis);
5101 if (!conn) {
5102 DEBUG(4,("Invalid connection in tdis\n"));
5103 reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
5104 END_PROFILE(SMBtdis);
5105 return;
5108 conn->used = False;
5110 close_cnum(conn,req->vuid);
5111 req->conn = NULL;
5113 reply_outbuf(req, 0, 0);
5114 END_PROFILE(SMBtdis);
5115 return;
5118 /****************************************************************************
5119 Reply to a echo.
5120 conn POINTER CAN BE NULL HERE !
5121 ****************************************************************************/
5123 void reply_echo(struct smb_request *req)
5125 connection_struct *conn = req->conn;
5126 struct smb_perfcount_data local_pcd;
5127 struct smb_perfcount_data *cur_pcd;
5128 int smb_reverb;
5129 int seq_num;
5131 START_PROFILE(SMBecho);
5133 smb_init_perfcount_data(&local_pcd);
5135 if (req->wct < 1) {
5136 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5137 END_PROFILE(SMBecho);
5138 return;
5141 smb_reverb = SVAL(req->vwv+0, 0);
5143 reply_outbuf(req, 1, req->buflen);
5145 /* copy any incoming data back out */
5146 if (req->buflen > 0) {
5147 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5150 if (smb_reverb > 100) {
5151 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5152 smb_reverb = 100;
5155 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5157 /* this makes sure we catch the request pcd */
5158 if (seq_num == smb_reverb) {
5159 cur_pcd = &req->pcd;
5160 } else {
5161 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5162 cur_pcd = &local_pcd;
5165 SSVAL(req->outbuf,smb_vwv0,seq_num);
5167 show_msg((char *)req->outbuf);
5168 if (!srv_send_smb(req->sconn,
5169 (char *)req->outbuf,
5170 true, req->seqnum+1,
5171 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5172 cur_pcd))
5173 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5176 DEBUG(3,("echo %d times\n", smb_reverb));
5178 TALLOC_FREE(req->outbuf);
5180 END_PROFILE(SMBecho);
5181 return;
5184 /****************************************************************************
5185 Reply to a printopen.
5186 ****************************************************************************/
5188 void reply_printopen(struct smb_request *req)
5190 connection_struct *conn = req->conn;
5191 files_struct *fsp;
5192 NTSTATUS status;
5194 START_PROFILE(SMBsplopen);
5196 if (req->wct < 2) {
5197 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5198 END_PROFILE(SMBsplopen);
5199 return;
5202 if (!CAN_PRINT(conn)) {
5203 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5204 END_PROFILE(SMBsplopen);
5205 return;
5208 status = file_new(req, conn, &fsp);
5209 if(!NT_STATUS_IS_OK(status)) {
5210 reply_nterror(req, status);
5211 END_PROFILE(SMBsplopen);
5212 return;
5215 /* Open for exclusive use, write only. */
5216 status = print_spool_open(fsp, NULL, req->vuid);
5218 if (!NT_STATUS_IS_OK(status)) {
5219 file_free(req, fsp);
5220 reply_nterror(req, status);
5221 END_PROFILE(SMBsplopen);
5222 return;
5225 reply_outbuf(req, 1, 0);
5226 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5228 DEBUG(3,("openprint fd=%d fnum=%d\n",
5229 fsp->fh->fd, fsp->fnum));
5231 END_PROFILE(SMBsplopen);
5232 return;
5235 /****************************************************************************
5236 Reply to a printclose.
5237 ****************************************************************************/
5239 void reply_printclose(struct smb_request *req)
5241 connection_struct *conn = req->conn;
5242 files_struct *fsp;
5243 NTSTATUS status;
5245 START_PROFILE(SMBsplclose);
5247 if (req->wct < 1) {
5248 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5249 END_PROFILE(SMBsplclose);
5250 return;
5253 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5255 if (!check_fsp(conn, req, fsp)) {
5256 END_PROFILE(SMBsplclose);
5257 return;
5260 if (!CAN_PRINT(conn)) {
5261 reply_force_doserror(req, ERRSRV, ERRerror);
5262 END_PROFILE(SMBsplclose);
5263 return;
5266 DEBUG(3,("printclose fd=%d fnum=%d\n",
5267 fsp->fh->fd,fsp->fnum));
5269 status = close_file(req, fsp, NORMAL_CLOSE);
5271 if(!NT_STATUS_IS_OK(status)) {
5272 reply_nterror(req, status);
5273 END_PROFILE(SMBsplclose);
5274 return;
5277 reply_outbuf(req, 0, 0);
5279 END_PROFILE(SMBsplclose);
5280 return;
5283 /****************************************************************************
5284 Reply to a printqueue.
5285 ****************************************************************************/
5287 void reply_printqueue(struct smb_request *req)
5289 connection_struct *conn = req->conn;
5290 int max_count;
5291 int start_index;
5293 START_PROFILE(SMBsplretq);
5295 if (req->wct < 2) {
5296 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5297 END_PROFILE(SMBsplretq);
5298 return;
5301 max_count = SVAL(req->vwv+0, 0);
5302 start_index = SVAL(req->vwv+1, 0);
5304 /* we used to allow the client to get the cnum wrong, but that
5305 is really quite gross and only worked when there was only
5306 one printer - I think we should now only accept it if they
5307 get it right (tridge) */
5308 if (!CAN_PRINT(conn)) {
5309 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5310 END_PROFILE(SMBsplretq);
5311 return;
5314 reply_outbuf(req, 2, 3);
5315 SSVAL(req->outbuf,smb_vwv0,0);
5316 SSVAL(req->outbuf,smb_vwv1,0);
5317 SCVAL(smb_buf(req->outbuf),0,1);
5318 SSVAL(smb_buf(req->outbuf),1,0);
5320 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5321 start_index, max_count));
5324 TALLOC_CTX *mem_ctx = talloc_tos();
5325 NTSTATUS status;
5326 WERROR werr;
5327 const char *sharename = lp_servicename(SNUM(conn));
5328 struct rpc_pipe_client *cli = NULL;
5329 struct dcerpc_binding_handle *b = NULL;
5330 struct policy_handle handle;
5331 struct spoolss_DevmodeContainer devmode_ctr;
5332 union spoolss_JobInfo *info;
5333 uint32_t count;
5334 uint32_t num_to_get;
5335 uint32_t first;
5336 uint32_t i;
5338 ZERO_STRUCT(handle);
5340 status = rpc_pipe_open_interface(conn,
5341 &ndr_table_spoolss.syntax_id,
5342 conn->session_info,
5343 &conn->sconn->client_id,
5344 conn->sconn->msg_ctx,
5345 &cli);
5346 if (!NT_STATUS_IS_OK(status)) {
5347 DEBUG(0, ("reply_printqueue: "
5348 "could not connect to spoolss: %s\n",
5349 nt_errstr(status)));
5350 reply_nterror(req, status);
5351 goto out;
5353 b = cli->binding_handle;
5355 ZERO_STRUCT(devmode_ctr);
5357 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5358 sharename,
5359 NULL, devmode_ctr,
5360 SEC_FLAG_MAXIMUM_ALLOWED,
5361 &handle,
5362 &werr);
5363 if (!NT_STATUS_IS_OK(status)) {
5364 reply_nterror(req, status);
5365 goto out;
5367 if (!W_ERROR_IS_OK(werr)) {
5368 reply_nterror(req, werror_to_ntstatus(werr));
5369 goto out;
5372 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5373 &handle,
5374 0, /* firstjob */
5375 0xff, /* numjobs */
5376 2, /* level */
5377 0, /* offered */
5378 &count,
5379 &info);
5380 if (!W_ERROR_IS_OK(werr)) {
5381 reply_nterror(req, werror_to_ntstatus(werr));
5382 goto out;
5385 if (max_count > 0) {
5386 first = start_index;
5387 } else {
5388 first = start_index + max_count + 1;
5391 if (first >= count) {
5392 num_to_get = first;
5393 } else {
5394 num_to_get = first + MIN(ABS(max_count), count - first);
5397 for (i = first; i < num_to_get; i++) {
5398 char blob[28];
5399 char *p = blob;
5400 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5401 int qstatus;
5402 uint16_t qrapjobid = pjobid_to_rap(sharename,
5403 info[i].info2.job_id);
5405 if (info[i].info2.status == JOB_STATUS_PRINTING) {
5406 qstatus = 2;
5407 } else {
5408 qstatus = 3;
5411 srv_put_dos_date2(p, 0, qtime);
5412 SCVAL(p, 4, qstatus);
5413 SSVAL(p, 5, qrapjobid);
5414 SIVAL(p, 7, info[i].info2.size);
5415 SCVAL(p, 11, 0);
5416 srvstr_push(blob, req->flags2, p+12,
5417 info[i].info2.notify_name, 16, STR_ASCII);
5419 if (message_push_blob(
5420 &req->outbuf,
5421 data_blob_const(
5422 blob, sizeof(blob))) == -1) {
5423 reply_nterror(req, NT_STATUS_NO_MEMORY);
5424 goto out;
5428 if (count > 0) {
5429 SSVAL(req->outbuf,smb_vwv0,count);
5430 SSVAL(req->outbuf,smb_vwv1,
5431 (max_count>0?first+count:first-1));
5432 SCVAL(smb_buf(req->outbuf),0,1);
5433 SSVAL(smb_buf(req->outbuf),1,28*count);
5437 DEBUG(3, ("%u entries returned in queue\n",
5438 (unsigned)count));
5440 out:
5441 if (b && is_valid_policy_hnd(&handle)) {
5442 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5447 END_PROFILE(SMBsplretq);
5448 return;
5451 /****************************************************************************
5452 Reply to a printwrite.
5453 ****************************************************************************/
5455 void reply_printwrite(struct smb_request *req)
5457 connection_struct *conn = req->conn;
5458 int numtowrite;
5459 const char *data;
5460 files_struct *fsp;
5462 START_PROFILE(SMBsplwr);
5464 if (req->wct < 1) {
5465 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5466 END_PROFILE(SMBsplwr);
5467 return;
5470 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5472 if (!check_fsp(conn, req, fsp)) {
5473 END_PROFILE(SMBsplwr);
5474 return;
5477 if (!fsp->print_file) {
5478 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5479 END_PROFILE(SMBsplwr);
5480 return;
5483 if (!CHECK_WRITE(fsp)) {
5484 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5485 END_PROFILE(SMBsplwr);
5486 return;
5489 numtowrite = SVAL(req->buf, 1);
5491 if (req->buflen < numtowrite + 3) {
5492 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5493 END_PROFILE(SMBsplwr);
5494 return;
5497 data = (const char *)req->buf + 3;
5499 if (write_file(req,fsp,data,(SMB_OFF_T)-1,numtowrite) != numtowrite) {
5500 reply_nterror(req, map_nt_error_from_unix(errno));
5501 END_PROFILE(SMBsplwr);
5502 return;
5505 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5507 END_PROFILE(SMBsplwr);
5508 return;
5511 /****************************************************************************
5512 Reply to a mkdir.
5513 ****************************************************************************/
5515 void reply_mkdir(struct smb_request *req)
5517 connection_struct *conn = req->conn;
5518 struct smb_filename *smb_dname = NULL;
5519 char *directory = NULL;
5520 NTSTATUS status;
5521 TALLOC_CTX *ctx = talloc_tos();
5523 START_PROFILE(SMBmkdir);
5525 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5526 STR_TERMINATE, &status);
5527 if (!NT_STATUS_IS_OK(status)) {
5528 reply_nterror(req, status);
5529 goto out;
5532 status = filename_convert(ctx, conn,
5533 req->flags2 & FLAGS2_DFS_PATHNAMES,
5534 directory,
5536 NULL,
5537 &smb_dname);
5538 if (!NT_STATUS_IS_OK(status)) {
5539 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5540 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5541 ERRSRV, ERRbadpath);
5542 goto out;
5544 reply_nterror(req, status);
5545 goto out;
5548 status = create_directory(conn, req, smb_dname);
5550 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5552 if (!NT_STATUS_IS_OK(status)) {
5554 if (!use_nt_status()
5555 && NT_STATUS_EQUAL(status,
5556 NT_STATUS_OBJECT_NAME_COLLISION)) {
5558 * Yes, in the DOS error code case we get a
5559 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5560 * samba4 torture test.
5562 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5565 reply_nterror(req, status);
5566 goto out;
5569 reply_outbuf(req, 0, 0);
5571 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5572 out:
5573 TALLOC_FREE(smb_dname);
5574 END_PROFILE(SMBmkdir);
5575 return;
5578 /****************************************************************************
5579 Reply to a rmdir.
5580 ****************************************************************************/
5582 void reply_rmdir(struct smb_request *req)
5584 connection_struct *conn = req->conn;
5585 struct smb_filename *smb_dname = NULL;
5586 char *directory = NULL;
5587 NTSTATUS status;
5588 TALLOC_CTX *ctx = talloc_tos();
5589 files_struct *fsp = NULL;
5590 int info = 0;
5591 struct smbd_server_connection *sconn = req->sconn;
5593 START_PROFILE(SMBrmdir);
5595 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5596 STR_TERMINATE, &status);
5597 if (!NT_STATUS_IS_OK(status)) {
5598 reply_nterror(req, status);
5599 goto out;
5602 status = filename_convert(ctx, conn,
5603 req->flags2 & FLAGS2_DFS_PATHNAMES,
5604 directory,
5606 NULL,
5607 &smb_dname);
5608 if (!NT_STATUS_IS_OK(status)) {
5609 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5610 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5611 ERRSRV, ERRbadpath);
5612 goto out;
5614 reply_nterror(req, status);
5615 goto out;
5618 if (is_ntfs_stream_smb_fname(smb_dname)) {
5619 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5620 goto out;
5623 status = SMB_VFS_CREATE_FILE(
5624 conn, /* conn */
5625 req, /* req */
5626 0, /* root_dir_fid */
5627 smb_dname, /* fname */
5628 DELETE_ACCESS, /* access_mask */
5629 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5630 FILE_SHARE_DELETE),
5631 FILE_OPEN, /* create_disposition*/
5632 FILE_DIRECTORY_FILE, /* create_options */
5633 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
5634 0, /* oplock_request */
5635 0, /* allocation_size */
5636 0, /* private_flags */
5637 NULL, /* sd */
5638 NULL, /* ea_list */
5639 &fsp, /* result */
5640 &info); /* pinfo */
5642 if (!NT_STATUS_IS_OK(status)) {
5643 if (open_was_deferred(req->mid)) {
5644 /* We have re-scheduled this call. */
5645 goto out;
5647 reply_nterror(req, status);
5648 goto out;
5651 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5652 if (!NT_STATUS_IS_OK(status)) {
5653 close_file(req, fsp, ERROR_CLOSE);
5654 reply_nterror(req, status);
5655 goto out;
5658 if (!set_delete_on_close(fsp, true, &conn->session_info->utok)) {
5659 close_file(req, fsp, ERROR_CLOSE);
5660 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5661 goto out;
5664 status = close_file(req, fsp, NORMAL_CLOSE);
5665 if (!NT_STATUS_IS_OK(status)) {
5666 reply_nterror(req, status);
5667 } else {
5668 reply_outbuf(req, 0, 0);
5671 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5673 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5674 out:
5675 TALLOC_FREE(smb_dname);
5676 END_PROFILE(SMBrmdir);
5677 return;
5680 /*******************************************************************
5681 Resolve wildcards in a filename rename.
5682 ********************************************************************/
5684 static bool resolve_wildcards(TALLOC_CTX *ctx,
5685 const char *name1,
5686 const char *name2,
5687 char **pp_newname)
5689 char *name2_copy = NULL;
5690 char *root1 = NULL;
5691 char *root2 = NULL;
5692 char *ext1 = NULL;
5693 char *ext2 = NULL;
5694 char *p,*p2, *pname1, *pname2;
5696 name2_copy = talloc_strdup(ctx, name2);
5697 if (!name2_copy) {
5698 return False;
5701 pname1 = strrchr_m(name1,'/');
5702 pname2 = strrchr_m(name2_copy,'/');
5704 if (!pname1 || !pname2) {
5705 return False;
5708 /* Truncate the copy of name2 at the last '/' */
5709 *pname2 = '\0';
5711 /* Now go past the '/' */
5712 pname1++;
5713 pname2++;
5715 root1 = talloc_strdup(ctx, pname1);
5716 root2 = talloc_strdup(ctx, pname2);
5718 if (!root1 || !root2) {
5719 return False;
5722 p = strrchr_m(root1,'.');
5723 if (p) {
5724 *p = 0;
5725 ext1 = talloc_strdup(ctx, p+1);
5726 } else {
5727 ext1 = talloc_strdup(ctx, "");
5729 p = strrchr_m(root2,'.');
5730 if (p) {
5731 *p = 0;
5732 ext2 = talloc_strdup(ctx, p+1);
5733 } else {
5734 ext2 = talloc_strdup(ctx, "");
5737 if (!ext1 || !ext2) {
5738 return False;
5741 p = root1;
5742 p2 = root2;
5743 while (*p2) {
5744 if (*p2 == '?') {
5745 /* Hmmm. Should this be mb-aware ? */
5746 *p2 = *p;
5747 p2++;
5748 } else if (*p2 == '*') {
5749 *p2 = '\0';
5750 root2 = talloc_asprintf(ctx, "%s%s",
5751 root2,
5753 if (!root2) {
5754 return False;
5756 break;
5757 } else {
5758 p2++;
5760 if (*p) {
5761 p++;
5765 p = ext1;
5766 p2 = ext2;
5767 while (*p2) {
5768 if (*p2 == '?') {
5769 /* Hmmm. Should this be mb-aware ? */
5770 *p2 = *p;
5771 p2++;
5772 } else if (*p2 == '*') {
5773 *p2 = '\0';
5774 ext2 = talloc_asprintf(ctx, "%s%s",
5775 ext2,
5777 if (!ext2) {
5778 return False;
5780 break;
5781 } else {
5782 p2++;
5784 if (*p) {
5785 p++;
5789 if (*ext2) {
5790 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5791 name2_copy,
5792 root2,
5793 ext2);
5794 } else {
5795 *pp_newname = talloc_asprintf(ctx, "%s/%s",
5796 name2_copy,
5797 root2);
5800 if (!*pp_newname) {
5801 return False;
5804 return True;
5807 /****************************************************************************
5808 Ensure open files have their names updated. Updated to notify other smbd's
5809 asynchronously.
5810 ****************************************************************************/
5812 static void rename_open_files(connection_struct *conn,
5813 struct share_mode_lock *lck,
5814 uint32_t orig_name_hash,
5815 const struct smb_filename *smb_fname_dst)
5817 files_struct *fsp;
5818 bool did_rename = False;
5819 NTSTATUS status;
5820 uint32_t new_name_hash;
5822 for(fsp = file_find_di_first(conn->sconn, lck->id); fsp;
5823 fsp = file_find_di_next(fsp)) {
5824 /* fsp_name is a relative path under the fsp. To change this for other
5825 sharepaths we need to manipulate relative paths. */
5826 /* TODO - create the absolute path and manipulate the newname
5827 relative to the sharepath. */
5828 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5829 continue;
5831 if (fsp->name_hash != orig_name_hash) {
5832 continue;
5834 DEBUG(10, ("rename_open_files: renaming file fnum %d "
5835 "(file_id %s) from %s -> %s\n", fsp->fnum,
5836 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5837 smb_fname_str_dbg(smb_fname_dst)));
5839 status = fsp_set_smb_fname(fsp, smb_fname_dst);
5840 if (NT_STATUS_IS_OK(status)) {
5841 did_rename = True;
5842 new_name_hash = fsp->name_hash;
5846 if (!did_rename) {
5847 DEBUG(10, ("rename_open_files: no open files on file_id %s "
5848 "for %s\n", file_id_string_tos(&lck->id),
5849 smb_fname_str_dbg(smb_fname_dst)));
5852 /* Send messages to all smbd's (not ourself) that the name has changed. */
5853 rename_share_filename(conn->sconn->msg_ctx, lck, conn->connectpath,
5854 orig_name_hash, new_name_hash,
5855 smb_fname_dst);
5859 /****************************************************************************
5860 We need to check if the source path is a parent directory of the destination
5861 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5862 refuse the rename with a sharing violation. Under UNIX the above call can
5863 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5864 probably need to check that the client is a Windows one before disallowing
5865 this as a UNIX client (one with UNIX extensions) can know the source is a
5866 symlink and make this decision intelligently. Found by an excellent bug
5867 report from <AndyLiebman@aol.com>.
5868 ****************************************************************************/
5870 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5871 const struct smb_filename *smb_fname_dst)
5873 const char *psrc = smb_fname_src->base_name;
5874 const char *pdst = smb_fname_dst->base_name;
5875 size_t slen;
5877 if (psrc[0] == '.' && psrc[1] == '/') {
5878 psrc += 2;
5880 if (pdst[0] == '.' && pdst[1] == '/') {
5881 pdst += 2;
5883 if ((slen = strlen(psrc)) > strlen(pdst)) {
5884 return False;
5886 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5890 * Do the notify calls from a rename
5893 static void notify_rename(connection_struct *conn, bool is_dir,
5894 const struct smb_filename *smb_fname_src,
5895 const struct smb_filename *smb_fname_dst)
5897 char *parent_dir_src = NULL;
5898 char *parent_dir_dst = NULL;
5899 uint32 mask;
5901 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5902 : FILE_NOTIFY_CHANGE_FILE_NAME;
5904 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5905 &parent_dir_src, NULL) ||
5906 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5907 &parent_dir_dst, NULL)) {
5908 goto out;
5911 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5912 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5913 smb_fname_src->base_name);
5914 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5915 smb_fname_dst->base_name);
5917 else {
5918 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5919 smb_fname_src->base_name);
5920 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5921 smb_fname_dst->base_name);
5924 /* this is a strange one. w2k3 gives an additional event for
5925 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5926 files, but not directories */
5927 if (!is_dir) {
5928 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5929 FILE_NOTIFY_CHANGE_ATTRIBUTES
5930 |FILE_NOTIFY_CHANGE_CREATION,
5931 smb_fname_dst->base_name);
5933 out:
5934 TALLOC_FREE(parent_dir_src);
5935 TALLOC_FREE(parent_dir_dst);
5938 /****************************************************************************
5939 Rename an open file - given an fsp.
5940 ****************************************************************************/
5942 NTSTATUS rename_internals_fsp(connection_struct *conn,
5943 files_struct *fsp,
5944 const struct smb_filename *smb_fname_dst_in,
5945 uint32 attrs,
5946 bool replace_if_exists)
5948 TALLOC_CTX *ctx = talloc_tos();
5949 struct smb_filename *smb_fname_dst = NULL;
5950 NTSTATUS status = NT_STATUS_OK;
5951 struct share_mode_lock *lck = NULL;
5952 bool dst_exists, old_is_stream, new_is_stream;
5954 status = check_name(conn, smb_fname_dst_in->base_name);
5955 if (!NT_STATUS_IS_OK(status)) {
5956 return status;
5959 /* Make a copy of the dst smb_fname structs */
5961 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
5962 if (!NT_STATUS_IS_OK(status)) {
5963 goto out;
5967 * Check for special case with case preserving and not
5968 * case sensitive. If the old last component differs from the original
5969 * last component only by case, then we should allow
5970 * the rename (user is trying to change the case of the
5971 * filename).
5973 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5974 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5975 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
5976 char *last_slash;
5977 char *fname_dst_lcomp_base_mod = NULL;
5978 struct smb_filename *smb_fname_orig_lcomp = NULL;
5981 * Get the last component of the destination name.
5983 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
5984 if (last_slash) {
5985 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
5986 } else {
5987 fname_dst_lcomp_base_mod = talloc_strdup(ctx, smb_fname_dst->base_name);
5989 if (!fname_dst_lcomp_base_mod) {
5990 status = NT_STATUS_NO_MEMORY;
5991 goto out;
5995 * Create an smb_filename struct using the original last
5996 * component of the destination.
5998 status = create_synthetic_smb_fname_split(ctx,
5999 smb_fname_dst->original_lcomp, NULL,
6000 &smb_fname_orig_lcomp);
6001 if (!NT_STATUS_IS_OK(status)) {
6002 TALLOC_FREE(fname_dst_lcomp_base_mod);
6003 goto out;
6006 /* If the base names only differ by case, use original. */
6007 if(!strcsequal(fname_dst_lcomp_base_mod,
6008 smb_fname_orig_lcomp->base_name)) {
6009 char *tmp;
6011 * Replace the modified last component with the
6012 * original.
6014 if (last_slash) {
6015 *last_slash = '\0'; /* Truncate at the '/' */
6016 tmp = talloc_asprintf(smb_fname_dst,
6017 "%s/%s",
6018 smb_fname_dst->base_name,
6019 smb_fname_orig_lcomp->base_name);
6020 } else {
6021 tmp = talloc_asprintf(smb_fname_dst,
6022 "%s",
6023 smb_fname_orig_lcomp->base_name);
6025 if (tmp == NULL) {
6026 status = NT_STATUS_NO_MEMORY;
6027 TALLOC_FREE(fname_dst_lcomp_base_mod);
6028 TALLOC_FREE(smb_fname_orig_lcomp);
6029 goto out;
6031 TALLOC_FREE(smb_fname_dst->base_name);
6032 smb_fname_dst->base_name = tmp;
6035 /* If the stream_names only differ by case, use original. */
6036 if(!strcsequal(smb_fname_dst->stream_name,
6037 smb_fname_orig_lcomp->stream_name)) {
6038 char *tmp = NULL;
6039 /* Use the original stream. */
6040 tmp = talloc_strdup(smb_fname_dst,
6041 smb_fname_orig_lcomp->stream_name);
6042 if (tmp == NULL) {
6043 status = NT_STATUS_NO_MEMORY;
6044 TALLOC_FREE(fname_dst_lcomp_base_mod);
6045 TALLOC_FREE(smb_fname_orig_lcomp);
6046 goto out;
6048 TALLOC_FREE(smb_fname_dst->stream_name);
6049 smb_fname_dst->stream_name = tmp;
6051 TALLOC_FREE(fname_dst_lcomp_base_mod);
6052 TALLOC_FREE(smb_fname_orig_lcomp);
6056 * If the src and dest names are identical - including case,
6057 * don't do the rename, just return success.
6060 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6061 strcsequal(fsp->fsp_name->stream_name,
6062 smb_fname_dst->stream_name)) {
6063 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6064 "- returning success\n",
6065 smb_fname_str_dbg(smb_fname_dst)));
6066 status = NT_STATUS_OK;
6067 goto out;
6070 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6071 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6073 /* Return the correct error code if both names aren't streams. */
6074 if (!old_is_stream && new_is_stream) {
6075 status = NT_STATUS_OBJECT_NAME_INVALID;
6076 goto out;
6079 if (old_is_stream && !new_is_stream) {
6080 status = NT_STATUS_INVALID_PARAMETER;
6081 goto out;
6084 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6086 if(!replace_if_exists && dst_exists) {
6087 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6088 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6089 smb_fname_str_dbg(smb_fname_dst)));
6090 status = NT_STATUS_OBJECT_NAME_COLLISION;
6091 goto out;
6094 if (dst_exists) {
6095 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6096 &smb_fname_dst->st);
6097 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6098 fileid);
6099 /* The file can be open when renaming a stream */
6100 if (dst_fsp && !new_is_stream) {
6101 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6102 status = NT_STATUS_ACCESS_DENIED;
6103 goto out;
6107 /* Ensure we have a valid stat struct for the source. */
6108 status = vfs_stat_fsp(fsp);
6109 if (!NT_STATUS_IS_OK(status)) {
6110 goto out;
6113 status = can_rename(conn, fsp, attrs);
6115 if (!NT_STATUS_IS_OK(status)) {
6116 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6117 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6118 smb_fname_str_dbg(smb_fname_dst)));
6119 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6120 status = NT_STATUS_ACCESS_DENIED;
6121 goto out;
6124 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6125 status = NT_STATUS_ACCESS_DENIED;
6128 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6129 NULL);
6132 * We have the file open ourselves, so not being able to get the
6133 * corresponding share mode lock is a fatal error.
6136 SMB_ASSERT(lck != NULL);
6138 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6139 uint32 create_options = fsp->fh->private_options;
6141 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6142 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6143 smb_fname_str_dbg(smb_fname_dst)));
6145 if (!lp_posix_pathnames() &&
6146 (lp_map_archive(SNUM(conn)) ||
6147 lp_store_dos_attributes(SNUM(conn)))) {
6148 /* We must set the archive bit on the newly
6149 renamed file. */
6150 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6151 uint32_t old_dosmode = dos_mode(conn,
6152 smb_fname_dst);
6153 file_set_dosmode(conn,
6154 smb_fname_dst,
6155 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6156 NULL,
6157 true);
6161 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6162 smb_fname_dst);
6164 rename_open_files(conn, lck, fsp->name_hash, smb_fname_dst);
6167 * A rename acts as a new file create w.r.t. allowing an initial delete
6168 * on close, probably because in Windows there is a new handle to the
6169 * new file. If initial delete on close was requested but not
6170 * originally set, we need to set it here. This is probably not 100% correct,
6171 * but will work for the CIFSFS client which in non-posix mode
6172 * depends on these semantics. JRA.
6175 if (create_options & FILE_DELETE_ON_CLOSE) {
6176 status = can_set_delete_on_close(fsp, 0);
6178 if (NT_STATUS_IS_OK(status)) {
6179 /* Note that here we set the *inital* delete on close flag,
6180 * not the regular one. The magic gets handled in close. */
6181 fsp->initial_delete_on_close = True;
6184 TALLOC_FREE(lck);
6185 status = NT_STATUS_OK;
6186 goto out;
6189 TALLOC_FREE(lck);
6191 if (errno == ENOTDIR || errno == EISDIR) {
6192 status = NT_STATUS_OBJECT_NAME_COLLISION;
6193 } else {
6194 status = map_nt_error_from_unix(errno);
6197 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6198 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6199 smb_fname_str_dbg(smb_fname_dst)));
6201 out:
6202 TALLOC_FREE(smb_fname_dst);
6204 return status;
6207 /****************************************************************************
6208 The guts of the rename command, split out so it may be called by the NT SMB
6209 code.
6210 ****************************************************************************/
6212 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6213 connection_struct *conn,
6214 struct smb_request *req,
6215 struct smb_filename *smb_fname_src,
6216 struct smb_filename *smb_fname_dst,
6217 uint32 attrs,
6218 bool replace_if_exists,
6219 bool src_has_wild,
6220 bool dest_has_wild,
6221 uint32_t access_mask)
6223 char *fname_src_dir = NULL;
6224 char *fname_src_mask = NULL;
6225 int count=0;
6226 NTSTATUS status = NT_STATUS_OK;
6227 struct smb_Dir *dir_hnd = NULL;
6228 const char *dname = NULL;
6229 char *talloced = NULL;
6230 long offset = 0;
6231 int create_options = 0;
6232 bool posix_pathnames = lp_posix_pathnames();
6235 * Split the old name into directory and last component
6236 * strings. Note that unix_convert may have stripped off a
6237 * leading ./ from both name and newname if the rename is
6238 * at the root of the share. We need to make sure either both
6239 * name and newname contain a / character or neither of them do
6240 * as this is checked in resolve_wildcards().
6243 /* Split up the directory from the filename/mask. */
6244 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6245 &fname_src_dir, &fname_src_mask);
6246 if (!NT_STATUS_IS_OK(status)) {
6247 status = NT_STATUS_NO_MEMORY;
6248 goto out;
6252 * We should only check the mangled cache
6253 * here if unix_convert failed. This means
6254 * that the path in 'mask' doesn't exist
6255 * on the file system and so we need to look
6256 * for a possible mangle. This patch from
6257 * Tine Smukavec <valentin.smukavec@hermes.si>.
6260 if (!VALID_STAT(smb_fname_src->st) &&
6261 mangle_is_mangled(fname_src_mask, conn->params)) {
6262 char *new_mask = NULL;
6263 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6264 conn->params);
6265 if (new_mask) {
6266 TALLOC_FREE(fname_src_mask);
6267 fname_src_mask = new_mask;
6271 if (!src_has_wild) {
6272 files_struct *fsp;
6275 * Only one file needs to be renamed. Append the mask back
6276 * onto the directory.
6278 TALLOC_FREE(smb_fname_src->base_name);
6279 if (ISDOT(fname_src_dir)) {
6280 /* Ensure we use canonical names on open. */
6281 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6282 "%s",
6283 fname_src_mask);
6284 } else {
6285 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6286 "%s/%s",
6287 fname_src_dir,
6288 fname_src_mask);
6290 if (!smb_fname_src->base_name) {
6291 status = NT_STATUS_NO_MEMORY;
6292 goto out;
6295 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6296 "case_preserve = %d, short case preserve = %d, "
6297 "directory = %s, newname = %s, "
6298 "last_component_dest = %s\n",
6299 conn->case_sensitive, conn->case_preserve,
6300 conn->short_case_preserve,
6301 smb_fname_str_dbg(smb_fname_src),
6302 smb_fname_str_dbg(smb_fname_dst),
6303 smb_fname_dst->original_lcomp));
6305 /* The dest name still may have wildcards. */
6306 if (dest_has_wild) {
6307 char *fname_dst_mod = NULL;
6308 if (!resolve_wildcards(smb_fname_dst,
6309 smb_fname_src->base_name,
6310 smb_fname_dst->base_name,
6311 &fname_dst_mod)) {
6312 DEBUG(6, ("rename_internals: resolve_wildcards "
6313 "%s %s failed\n",
6314 smb_fname_src->base_name,
6315 smb_fname_dst->base_name));
6316 status = NT_STATUS_NO_MEMORY;
6317 goto out;
6319 TALLOC_FREE(smb_fname_dst->base_name);
6320 smb_fname_dst->base_name = fname_dst_mod;
6323 ZERO_STRUCT(smb_fname_src->st);
6324 if (posix_pathnames) {
6325 SMB_VFS_LSTAT(conn, smb_fname_src);
6326 } else {
6327 SMB_VFS_STAT(conn, smb_fname_src);
6330 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6331 create_options |= FILE_DIRECTORY_FILE;
6334 status = SMB_VFS_CREATE_FILE(
6335 conn, /* conn */
6336 req, /* req */
6337 0, /* root_dir_fid */
6338 smb_fname_src, /* fname */
6339 access_mask, /* access_mask */
6340 (FILE_SHARE_READ | /* share_access */
6341 FILE_SHARE_WRITE),
6342 FILE_OPEN, /* create_disposition*/
6343 create_options, /* create_options */
6344 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6345 0, /* oplock_request */
6346 0, /* allocation_size */
6347 0, /* private_flags */
6348 NULL, /* sd */
6349 NULL, /* ea_list */
6350 &fsp, /* result */
6351 NULL); /* pinfo */
6353 if (!NT_STATUS_IS_OK(status)) {
6354 DEBUG(3, ("Could not open rename source %s: %s\n",
6355 smb_fname_str_dbg(smb_fname_src),
6356 nt_errstr(status)));
6357 goto out;
6360 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6361 attrs, replace_if_exists);
6363 close_file(req, fsp, NORMAL_CLOSE);
6365 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6366 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6367 smb_fname_str_dbg(smb_fname_dst)));
6369 goto out;
6373 * Wildcards - process each file that matches.
6375 if (strequal(fname_src_mask, "????????.???")) {
6376 TALLOC_FREE(fname_src_mask);
6377 fname_src_mask = talloc_strdup(ctx, "*");
6378 if (!fname_src_mask) {
6379 status = NT_STATUS_NO_MEMORY;
6380 goto out;
6384 status = check_name(conn, fname_src_dir);
6385 if (!NT_STATUS_IS_OK(status)) {
6386 goto out;
6389 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6390 attrs);
6391 if (dir_hnd == NULL) {
6392 status = map_nt_error_from_unix(errno);
6393 goto out;
6396 status = NT_STATUS_NO_SUCH_FILE;
6398 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6399 * - gentest fix. JRA
6402 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6403 &talloced))) {
6404 files_struct *fsp = NULL;
6405 char *destname = NULL;
6406 bool sysdir_entry = False;
6408 /* Quick check for "." and ".." */
6409 if (ISDOT(dname) || ISDOTDOT(dname)) {
6410 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
6411 sysdir_entry = True;
6412 } else {
6413 TALLOC_FREE(talloced);
6414 continue;
6418 if (!is_visible_file(conn, fname_src_dir, dname,
6419 &smb_fname_src->st, false)) {
6420 TALLOC_FREE(talloced);
6421 continue;
6424 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6425 TALLOC_FREE(talloced);
6426 continue;
6429 if (sysdir_entry) {
6430 status = NT_STATUS_OBJECT_NAME_INVALID;
6431 break;
6434 TALLOC_FREE(smb_fname_src->base_name);
6435 if (ISDOT(fname_src_dir)) {
6436 /* Ensure we use canonical names on open. */
6437 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6438 "%s",
6439 dname);
6440 } else {
6441 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6442 "%s/%s",
6443 fname_src_dir,
6444 dname);
6446 if (!smb_fname_src->base_name) {
6447 status = NT_STATUS_NO_MEMORY;
6448 goto out;
6451 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6452 smb_fname_dst->base_name,
6453 &destname)) {
6454 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6455 smb_fname_src->base_name, destname));
6456 TALLOC_FREE(talloced);
6457 continue;
6459 if (!destname) {
6460 status = NT_STATUS_NO_MEMORY;
6461 goto out;
6464 TALLOC_FREE(smb_fname_dst->base_name);
6465 smb_fname_dst->base_name = destname;
6467 ZERO_STRUCT(smb_fname_src->st);
6468 if (posix_pathnames) {
6469 SMB_VFS_LSTAT(conn, smb_fname_src);
6470 } else {
6471 SMB_VFS_STAT(conn, smb_fname_src);
6474 create_options = 0;
6476 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6477 create_options |= FILE_DIRECTORY_FILE;
6480 status = SMB_VFS_CREATE_FILE(
6481 conn, /* conn */
6482 req, /* req */
6483 0, /* root_dir_fid */
6484 smb_fname_src, /* fname */
6485 access_mask, /* access_mask */
6486 (FILE_SHARE_READ | /* share_access */
6487 FILE_SHARE_WRITE),
6488 FILE_OPEN, /* create_disposition*/
6489 create_options, /* create_options */
6490 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6491 0, /* oplock_request */
6492 0, /* allocation_size */
6493 0, /* private_flags */
6494 NULL, /* sd */
6495 NULL, /* ea_list */
6496 &fsp, /* result */
6497 NULL); /* pinfo */
6499 if (!NT_STATUS_IS_OK(status)) {
6500 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6501 "returned %s rename %s -> %s\n",
6502 nt_errstr(status),
6503 smb_fname_str_dbg(smb_fname_src),
6504 smb_fname_str_dbg(smb_fname_dst)));
6505 break;
6508 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6509 dname);
6510 if (!smb_fname_dst->original_lcomp) {
6511 status = NT_STATUS_NO_MEMORY;
6512 goto out;
6515 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6516 attrs, replace_if_exists);
6518 close_file(req, fsp, NORMAL_CLOSE);
6520 if (!NT_STATUS_IS_OK(status)) {
6521 DEBUG(3, ("rename_internals_fsp returned %s for "
6522 "rename %s -> %s\n", nt_errstr(status),
6523 smb_fname_str_dbg(smb_fname_src),
6524 smb_fname_str_dbg(smb_fname_dst)));
6525 break;
6528 count++;
6530 DEBUG(3,("rename_internals: doing rename on %s -> "
6531 "%s\n", smb_fname_str_dbg(smb_fname_src),
6532 smb_fname_str_dbg(smb_fname_src)));
6533 TALLOC_FREE(talloced);
6535 TALLOC_FREE(dir_hnd);
6537 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6538 status = map_nt_error_from_unix(errno);
6541 out:
6542 TALLOC_FREE(talloced);
6543 TALLOC_FREE(fname_src_dir);
6544 TALLOC_FREE(fname_src_mask);
6545 return status;
6548 /****************************************************************************
6549 Reply to a mv.
6550 ****************************************************************************/
6552 void reply_mv(struct smb_request *req)
6554 connection_struct *conn = req->conn;
6555 char *name = NULL;
6556 char *newname = NULL;
6557 const char *p;
6558 uint32 attrs;
6559 NTSTATUS status;
6560 bool src_has_wcard = False;
6561 bool dest_has_wcard = False;
6562 TALLOC_CTX *ctx = talloc_tos();
6563 struct smb_filename *smb_fname_src = NULL;
6564 struct smb_filename *smb_fname_dst = NULL;
6565 bool stream_rename = false;
6567 START_PROFILE(SMBmv);
6569 if (req->wct < 1) {
6570 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6571 goto out;
6574 attrs = SVAL(req->vwv+0, 0);
6576 p = (const char *)req->buf + 1;
6577 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6578 &status, &src_has_wcard);
6579 if (!NT_STATUS_IS_OK(status)) {
6580 reply_nterror(req, status);
6581 goto out;
6583 p++;
6584 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6585 &status, &dest_has_wcard);
6586 if (!NT_STATUS_IS_OK(status)) {
6587 reply_nterror(req, status);
6588 goto out;
6591 if (!lp_posix_pathnames()) {
6592 /* The newname must begin with a ':' if the
6593 name contains a ':'. */
6594 if (strchr_m(name, ':')) {
6595 if (newname[0] != ':') {
6596 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6597 goto out;
6599 stream_rename = true;
6603 status = filename_convert(ctx,
6604 conn,
6605 req->flags2 & FLAGS2_DFS_PATHNAMES,
6606 name,
6607 UCF_COND_ALLOW_WCARD_LCOMP,
6608 &src_has_wcard,
6609 &smb_fname_src);
6611 if (!NT_STATUS_IS_OK(status)) {
6612 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6613 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6614 ERRSRV, ERRbadpath);
6615 goto out;
6617 reply_nterror(req, status);
6618 goto out;
6621 status = filename_convert(ctx,
6622 conn,
6623 req->flags2 & FLAGS2_DFS_PATHNAMES,
6624 newname,
6625 UCF_COND_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP,
6626 &dest_has_wcard,
6627 &smb_fname_dst);
6629 if (!NT_STATUS_IS_OK(status)) {
6630 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6631 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6632 ERRSRV, ERRbadpath);
6633 goto out;
6635 reply_nterror(req, status);
6636 goto out;
6639 if (stream_rename) {
6640 /* smb_fname_dst->base_name must be the same as
6641 smb_fname_src->base_name. */
6642 TALLOC_FREE(smb_fname_dst->base_name);
6643 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
6644 smb_fname_src->base_name);
6645 if (!smb_fname_dst->base_name) {
6646 reply_nterror(req, NT_STATUS_NO_MEMORY);
6647 goto out;
6651 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6652 smb_fname_str_dbg(smb_fname_dst)));
6654 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6655 attrs, False, src_has_wcard, dest_has_wcard,
6656 DELETE_ACCESS);
6657 if (!NT_STATUS_IS_OK(status)) {
6658 if (open_was_deferred(req->mid)) {
6659 /* We have re-scheduled this call. */
6660 goto out;
6662 reply_nterror(req, status);
6663 goto out;
6666 reply_outbuf(req, 0, 0);
6667 out:
6668 TALLOC_FREE(smb_fname_src);
6669 TALLOC_FREE(smb_fname_dst);
6670 END_PROFILE(SMBmv);
6671 return;
6674 /*******************************************************************
6675 Copy a file as part of a reply_copy.
6676 ******************************************************************/
6679 * TODO: check error codes on all callers
6682 NTSTATUS copy_file(TALLOC_CTX *ctx,
6683 connection_struct *conn,
6684 struct smb_filename *smb_fname_src,
6685 struct smb_filename *smb_fname_dst,
6686 int ofun,
6687 int count,
6688 bool target_is_directory)
6690 struct smb_filename *smb_fname_dst_tmp = NULL;
6691 SMB_OFF_T ret=-1;
6692 files_struct *fsp1,*fsp2;
6693 uint32 dosattrs;
6694 uint32 new_create_disposition;
6695 NTSTATUS status;
6698 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6699 if (!NT_STATUS_IS_OK(status)) {
6700 return status;
6704 * If the target is a directory, extract the last component from the
6705 * src filename and append it to the dst filename
6707 if (target_is_directory) {
6708 const char *p;
6710 /* dest/target can't be a stream if it's a directory. */
6711 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6713 p = strrchr_m(smb_fname_src->base_name,'/');
6714 if (p) {
6715 p++;
6716 } else {
6717 p = smb_fname_src->base_name;
6719 smb_fname_dst_tmp->base_name =
6720 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6722 if (!smb_fname_dst_tmp->base_name) {
6723 status = NT_STATUS_NO_MEMORY;
6724 goto out;
6728 status = vfs_file_exist(conn, smb_fname_src);
6729 if (!NT_STATUS_IS_OK(status)) {
6730 goto out;
6733 if (!target_is_directory && count) {
6734 new_create_disposition = FILE_OPEN;
6735 } else {
6736 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
6737 0, ofun,
6738 NULL, NULL,
6739 &new_create_disposition,
6740 NULL,
6741 NULL)) {
6742 status = NT_STATUS_INVALID_PARAMETER;
6743 goto out;
6747 /* Open the src file for reading. */
6748 status = SMB_VFS_CREATE_FILE(
6749 conn, /* conn */
6750 NULL, /* req */
6751 0, /* root_dir_fid */
6752 smb_fname_src, /* fname */
6753 FILE_GENERIC_READ, /* access_mask */
6754 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6755 FILE_OPEN, /* create_disposition*/
6756 0, /* create_options */
6757 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6758 INTERNAL_OPEN_ONLY, /* oplock_request */
6759 0, /* allocation_size */
6760 0, /* private_flags */
6761 NULL, /* sd */
6762 NULL, /* ea_list */
6763 &fsp1, /* result */
6764 NULL); /* psbuf */
6766 if (!NT_STATUS_IS_OK(status)) {
6767 goto out;
6770 dosattrs = dos_mode(conn, smb_fname_src);
6772 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6773 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6776 /* Open the dst file for writing. */
6777 status = SMB_VFS_CREATE_FILE(
6778 conn, /* conn */
6779 NULL, /* req */
6780 0, /* root_dir_fid */
6781 smb_fname_dst, /* fname */
6782 FILE_GENERIC_WRITE, /* access_mask */
6783 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
6784 new_create_disposition, /* create_disposition*/
6785 0, /* create_options */
6786 dosattrs, /* file_attributes */
6787 INTERNAL_OPEN_ONLY, /* oplock_request */
6788 0, /* allocation_size */
6789 0, /* private_flags */
6790 NULL, /* sd */
6791 NULL, /* ea_list */
6792 &fsp2, /* result */
6793 NULL); /* psbuf */
6795 if (!NT_STATUS_IS_OK(status)) {
6796 close_file(NULL, fsp1, ERROR_CLOSE);
6797 goto out;
6800 if (ofun & OPENX_FILE_EXISTS_OPEN) {
6801 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
6802 if (ret == -1) {
6803 DEBUG(0, ("error - vfs lseek returned error %s\n",
6804 strerror(errno)));
6805 status = map_nt_error_from_unix(errno);
6806 close_file(NULL, fsp1, ERROR_CLOSE);
6807 close_file(NULL, fsp2, ERROR_CLOSE);
6808 goto out;
6812 /* Do the actual copy. */
6813 if (smb_fname_src->st.st_ex_size) {
6814 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6815 } else {
6816 ret = 0;
6819 close_file(NULL, fsp1, NORMAL_CLOSE);
6821 /* Ensure the modtime is set correctly on the destination file. */
6822 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6825 * As we are opening fsp1 read-only we only expect
6826 * an error on close on fsp2 if we are out of space.
6827 * Thus we don't look at the error return from the
6828 * close of fsp1.
6830 status = close_file(NULL, fsp2, NORMAL_CLOSE);
6832 if (!NT_STATUS_IS_OK(status)) {
6833 goto out;
6836 if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6837 status = NT_STATUS_DISK_FULL;
6838 goto out;
6841 status = NT_STATUS_OK;
6843 out:
6844 TALLOC_FREE(smb_fname_dst_tmp);
6845 return status;
6848 /****************************************************************************
6849 Reply to a file copy.
6850 ****************************************************************************/
6852 void reply_copy(struct smb_request *req)
6854 connection_struct *conn = req->conn;
6855 struct smb_filename *smb_fname_src = NULL;
6856 struct smb_filename *smb_fname_dst = NULL;
6857 char *fname_src = NULL;
6858 char *fname_dst = NULL;
6859 char *fname_src_mask = NULL;
6860 char *fname_src_dir = NULL;
6861 const char *p;
6862 int count=0;
6863 int error = ERRnoaccess;
6864 int tid2;
6865 int ofun;
6866 int flags;
6867 bool target_is_directory=False;
6868 bool source_has_wild = False;
6869 bool dest_has_wild = False;
6870 NTSTATUS status;
6871 TALLOC_CTX *ctx = talloc_tos();
6873 START_PROFILE(SMBcopy);
6875 if (req->wct < 3) {
6876 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6877 goto out;
6880 tid2 = SVAL(req->vwv+0, 0);
6881 ofun = SVAL(req->vwv+1, 0);
6882 flags = SVAL(req->vwv+2, 0);
6884 p = (const char *)req->buf;
6885 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6886 &status, &source_has_wild);
6887 if (!NT_STATUS_IS_OK(status)) {
6888 reply_nterror(req, status);
6889 goto out;
6891 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6892 &status, &dest_has_wild);
6893 if (!NT_STATUS_IS_OK(status)) {
6894 reply_nterror(req, status);
6895 goto out;
6898 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6900 if (tid2 != conn->cnum) {
6901 /* can't currently handle inter share copies XXXX */
6902 DEBUG(3,("Rejecting inter-share copy\n"));
6903 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
6904 goto out;
6907 status = filename_convert(ctx, conn,
6908 req->flags2 & FLAGS2_DFS_PATHNAMES,
6909 fname_src,
6910 UCF_COND_ALLOW_WCARD_LCOMP,
6911 &source_has_wild,
6912 &smb_fname_src);
6913 if (!NT_STATUS_IS_OK(status)) {
6914 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6915 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6916 ERRSRV, ERRbadpath);
6917 goto out;
6919 reply_nterror(req, status);
6920 goto out;
6923 status = filename_convert(ctx, conn,
6924 req->flags2 & FLAGS2_DFS_PATHNAMES,
6925 fname_dst,
6926 UCF_COND_ALLOW_WCARD_LCOMP,
6927 &dest_has_wild,
6928 &smb_fname_dst);
6929 if (!NT_STATUS_IS_OK(status)) {
6930 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6931 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6932 ERRSRV, ERRbadpath);
6933 goto out;
6935 reply_nterror(req, status);
6936 goto out;
6939 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6941 if ((flags&1) && target_is_directory) {
6942 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
6943 goto out;
6946 if ((flags&2) && !target_is_directory) {
6947 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
6948 goto out;
6951 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6952 /* wants a tree copy! XXXX */
6953 DEBUG(3,("Rejecting tree copy\n"));
6954 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6955 goto out;
6958 /* Split up the directory from the filename/mask. */
6959 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6960 &fname_src_dir, &fname_src_mask);
6961 if (!NT_STATUS_IS_OK(status)) {
6962 reply_nterror(req, NT_STATUS_NO_MEMORY);
6963 goto out;
6967 * We should only check the mangled cache
6968 * here if unix_convert failed. This means
6969 * that the path in 'mask' doesn't exist
6970 * on the file system and so we need to look
6971 * for a possible mangle. This patch from
6972 * Tine Smukavec <valentin.smukavec@hermes.si>.
6974 if (!VALID_STAT(smb_fname_src->st) &&
6975 mangle_is_mangled(fname_src_mask, conn->params)) {
6976 char *new_mask = NULL;
6977 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
6978 &new_mask, conn->params);
6980 /* Use demangled name if one was successfully found. */
6981 if (new_mask) {
6982 TALLOC_FREE(fname_src_mask);
6983 fname_src_mask = new_mask;
6987 if (!source_has_wild) {
6990 * Only one file needs to be copied. Append the mask back onto
6991 * the directory.
6993 TALLOC_FREE(smb_fname_src->base_name);
6994 if (ISDOT(fname_src_dir)) {
6995 /* Ensure we use canonical names on open. */
6996 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6997 "%s",
6998 fname_src_mask);
6999 } else {
7000 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7001 "%s/%s",
7002 fname_src_dir,
7003 fname_src_mask);
7005 if (!smb_fname_src->base_name) {
7006 reply_nterror(req, NT_STATUS_NO_MEMORY);
7007 goto out;
7010 if (dest_has_wild) {
7011 char *fname_dst_mod = NULL;
7012 if (!resolve_wildcards(smb_fname_dst,
7013 smb_fname_src->base_name,
7014 smb_fname_dst->base_name,
7015 &fname_dst_mod)) {
7016 reply_nterror(req, NT_STATUS_NO_MEMORY);
7017 goto out;
7019 TALLOC_FREE(smb_fname_dst->base_name);
7020 smb_fname_dst->base_name = fname_dst_mod;
7023 status = check_name(conn, smb_fname_src->base_name);
7024 if (!NT_STATUS_IS_OK(status)) {
7025 reply_nterror(req, status);
7026 goto out;
7029 status = check_name(conn, smb_fname_dst->base_name);
7030 if (!NT_STATUS_IS_OK(status)) {
7031 reply_nterror(req, status);
7032 goto out;
7035 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7036 ofun, count, target_is_directory);
7038 if(!NT_STATUS_IS_OK(status)) {
7039 reply_nterror(req, status);
7040 goto out;
7041 } else {
7042 count++;
7044 } else {
7045 struct smb_Dir *dir_hnd = NULL;
7046 const char *dname = NULL;
7047 char *talloced = NULL;
7048 long offset = 0;
7051 * There is a wildcard that requires us to actually read the
7052 * src dir and copy each file matching the mask to the dst.
7053 * Right now streams won't be copied, but this could
7054 * presumably be added with a nested loop for reach dir entry.
7056 SMB_ASSERT(!smb_fname_src->stream_name);
7057 SMB_ASSERT(!smb_fname_dst->stream_name);
7059 smb_fname_src->stream_name = NULL;
7060 smb_fname_dst->stream_name = NULL;
7062 if (strequal(fname_src_mask,"????????.???")) {
7063 TALLOC_FREE(fname_src_mask);
7064 fname_src_mask = talloc_strdup(ctx, "*");
7065 if (!fname_src_mask) {
7066 reply_nterror(req, NT_STATUS_NO_MEMORY);
7067 goto out;
7071 status = check_name(conn, fname_src_dir);
7072 if (!NT_STATUS_IS_OK(status)) {
7073 reply_nterror(req, status);
7074 goto out;
7077 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
7078 if (dir_hnd == NULL) {
7079 status = map_nt_error_from_unix(errno);
7080 reply_nterror(req, status);
7081 goto out;
7084 error = ERRbadfile;
7086 /* Iterate over the src dir copying each entry to the dst. */
7087 while ((dname = ReadDirName(dir_hnd, &offset,
7088 &smb_fname_src->st, &talloced))) {
7089 char *destname = NULL;
7091 if (ISDOT(dname) || ISDOTDOT(dname)) {
7092 TALLOC_FREE(talloced);
7093 continue;
7096 if (!is_visible_file(conn, fname_src_dir, dname,
7097 &smb_fname_src->st, false)) {
7098 TALLOC_FREE(talloced);
7099 continue;
7102 if(!mask_match(dname, fname_src_mask,
7103 conn->case_sensitive)) {
7104 TALLOC_FREE(talloced);
7105 continue;
7108 error = ERRnoaccess;
7110 /* Get the src smb_fname struct setup. */
7111 TALLOC_FREE(smb_fname_src->base_name);
7112 if (ISDOT(fname_src_dir)) {
7113 /* Ensure we use canonical names on open. */
7114 smb_fname_src->base_name =
7115 talloc_asprintf(smb_fname_src, "%s",
7116 dname);
7117 } else {
7118 smb_fname_src->base_name =
7119 talloc_asprintf(smb_fname_src, "%s/%s",
7120 fname_src_dir, dname);
7123 if (!smb_fname_src->base_name) {
7124 TALLOC_FREE(dir_hnd);
7125 TALLOC_FREE(talloced);
7126 reply_nterror(req, NT_STATUS_NO_MEMORY);
7127 goto out;
7130 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7131 smb_fname_dst->base_name,
7132 &destname)) {
7133 TALLOC_FREE(talloced);
7134 continue;
7136 if (!destname) {
7137 TALLOC_FREE(dir_hnd);
7138 TALLOC_FREE(talloced);
7139 reply_nterror(req, NT_STATUS_NO_MEMORY);
7140 goto out;
7143 TALLOC_FREE(smb_fname_dst->base_name);
7144 smb_fname_dst->base_name = destname;
7146 status = check_name(conn, smb_fname_src->base_name);
7147 if (!NT_STATUS_IS_OK(status)) {
7148 TALLOC_FREE(dir_hnd);
7149 TALLOC_FREE(talloced);
7150 reply_nterror(req, status);
7151 goto out;
7154 status = check_name(conn, smb_fname_dst->base_name);
7155 if (!NT_STATUS_IS_OK(status)) {
7156 TALLOC_FREE(dir_hnd);
7157 TALLOC_FREE(talloced);
7158 reply_nterror(req, status);
7159 goto out;
7162 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7163 smb_fname_src->base_name,
7164 smb_fname_dst->base_name));
7166 status = copy_file(ctx, conn, smb_fname_src,
7167 smb_fname_dst, ofun, count,
7168 target_is_directory);
7169 if (NT_STATUS_IS_OK(status)) {
7170 count++;
7173 TALLOC_FREE(talloced);
7175 TALLOC_FREE(dir_hnd);
7178 if (count == 0) {
7179 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7180 goto out;
7183 reply_outbuf(req, 1, 0);
7184 SSVAL(req->outbuf,smb_vwv0,count);
7185 out:
7186 TALLOC_FREE(smb_fname_src);
7187 TALLOC_FREE(smb_fname_dst);
7188 TALLOC_FREE(fname_src);
7189 TALLOC_FREE(fname_dst);
7190 TALLOC_FREE(fname_src_mask);
7191 TALLOC_FREE(fname_src_dir);
7193 END_PROFILE(SMBcopy);
7194 return;
7197 #undef DBGC_CLASS
7198 #define DBGC_CLASS DBGC_LOCKING
7200 /****************************************************************************
7201 Get a lock pid, dealing with large count requests.
7202 ****************************************************************************/
7204 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7205 bool large_file_format)
7207 if(!large_file_format)
7208 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7209 else
7210 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7213 /****************************************************************************
7214 Get a lock count, dealing with large count requests.
7215 ****************************************************************************/
7217 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7218 bool large_file_format)
7220 uint64_t count = 0;
7222 if(!large_file_format) {
7223 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7224 } else {
7226 #if defined(HAVE_LONGLONG)
7227 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7228 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7229 #else /* HAVE_LONGLONG */
7232 * NT4.x seems to be broken in that it sends large file (64 bit)
7233 * lockingX calls even if the CAP_LARGE_FILES was *not*
7234 * negotiated. For boxes without large unsigned ints truncate the
7235 * lock count by dropping the top 32 bits.
7238 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7239 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7240 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7241 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7242 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7245 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7246 #endif /* HAVE_LONGLONG */
7249 return count;
7252 #if !defined(HAVE_LONGLONG)
7253 /****************************************************************************
7254 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7255 ****************************************************************************/
7257 static uint32 map_lock_offset(uint32 high, uint32 low)
7259 unsigned int i;
7260 uint32 mask = 0;
7261 uint32 highcopy = high;
7264 * Try and find out how many significant bits there are in high.
7267 for(i = 0; highcopy; i++)
7268 highcopy >>= 1;
7271 * We use 31 bits not 32 here as POSIX
7272 * lock offsets may not be negative.
7275 mask = (~0) << (31 - i);
7277 if(low & mask)
7278 return 0; /* Fail. */
7280 high <<= (31 - i);
7282 return (high|low);
7284 #endif /* !defined(HAVE_LONGLONG) */
7286 /****************************************************************************
7287 Get a lock offset, dealing with large offset requests.
7288 ****************************************************************************/
7290 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7291 bool large_file_format, bool *err)
7293 uint64_t offset = 0;
7295 *err = False;
7297 if(!large_file_format) {
7298 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7299 } else {
7301 #if defined(HAVE_LONGLONG)
7302 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7303 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7304 #else /* HAVE_LONGLONG */
7307 * NT4.x seems to be broken in that it sends large file (64 bit)
7308 * lockingX calls even if the CAP_LARGE_FILES was *not*
7309 * negotiated. For boxes without large unsigned ints mangle the
7310 * lock offset by mapping the top 32 bits onto the lower 32.
7313 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7314 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7315 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7316 uint32 new_low = 0;
7318 if((new_low = map_lock_offset(high, low)) == 0) {
7319 *err = True;
7320 return (uint64_t)-1;
7323 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7324 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7325 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7326 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7329 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7330 #endif /* HAVE_LONGLONG */
7333 return offset;
7336 NTSTATUS smbd_do_locking(struct smb_request *req,
7337 files_struct *fsp,
7338 uint8_t type,
7339 int32_t timeout,
7340 uint16_t num_ulocks,
7341 struct smbd_lock_element *ulocks,
7342 uint16_t num_locks,
7343 struct smbd_lock_element *locks,
7344 bool *async)
7346 connection_struct *conn = req->conn;
7347 int i;
7348 NTSTATUS status = NT_STATUS_OK;
7350 *async = false;
7352 /* Data now points at the beginning of the list
7353 of smb_unlkrng structs */
7354 for(i = 0; i < (int)num_ulocks; i++) {
7355 struct smbd_lock_element *e = &ulocks[i];
7357 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7358 "pid %u, file %s\n",
7359 (double)e->offset,
7360 (double)e->count,
7361 (unsigned int)e->smblctx,
7362 fsp_str_dbg(fsp)));
7364 if (e->brltype != UNLOCK_LOCK) {
7365 /* this can only happen with SMB2 */
7366 return NT_STATUS_INVALID_PARAMETER;
7369 status = do_unlock(req->sconn->msg_ctx,
7370 fsp,
7371 e->smblctx,
7372 e->count,
7373 e->offset,
7374 WINDOWS_LOCK);
7376 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7377 nt_errstr(status)));
7379 if (!NT_STATUS_IS_OK(status)) {
7380 return status;
7384 /* Setup the timeout in seconds. */
7386 if (!lp_blocking_locks(SNUM(conn))) {
7387 timeout = 0;
7390 /* Data now points at the beginning of the list
7391 of smb_lkrng structs */
7393 for(i = 0; i < (int)num_locks; i++) {
7394 struct smbd_lock_element *e = &locks[i];
7396 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7397 "%llu, file %s timeout = %d\n",
7398 (double)e->offset,
7399 (double)e->count,
7400 (unsigned long long)e->smblctx,
7401 fsp_str_dbg(fsp),
7402 (int)timeout));
7404 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7405 struct blocking_lock_record *blr = NULL;
7407 if (num_locks > 1) {
7409 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7410 * if the lock vector contains one entry. When given mutliple cancel
7411 * requests in a single PDU we expect the server to return an
7412 * error. Windows servers seem to accept the request but only
7413 * cancel the first lock.
7414 * JRA - Do what Windows does (tm) :-).
7417 #if 0
7418 /* MS-CIFS (2.2.4.32.1) behavior. */
7419 return NT_STATUS_DOS(ERRDOS,
7420 ERRcancelviolation);
7421 #else
7422 /* Windows behavior. */
7423 if (i != 0) {
7424 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7425 "cancel request\n"));
7426 continue;
7428 #endif
7431 if (lp_blocking_locks(SNUM(conn))) {
7433 /* Schedule a message to ourselves to
7434 remove the blocking lock record and
7435 return the right error. */
7437 blr = blocking_lock_cancel_smb1(fsp,
7438 e->smblctx,
7439 e->offset,
7440 e->count,
7441 WINDOWS_LOCK,
7442 type,
7443 NT_STATUS_FILE_LOCK_CONFLICT);
7444 if (blr == NULL) {
7445 return NT_STATUS_DOS(
7446 ERRDOS,
7447 ERRcancelviolation);
7450 /* Remove a matching pending lock. */
7451 status = do_lock_cancel(fsp,
7452 e->smblctx,
7453 e->count,
7454 e->offset,
7455 WINDOWS_LOCK,
7456 blr);
7457 } else {
7458 bool blocking_lock = timeout ? true : false;
7459 bool defer_lock = false;
7460 struct byte_range_lock *br_lck;
7461 uint64_t block_smblctx;
7463 br_lck = do_lock(req->sconn->msg_ctx,
7464 fsp,
7465 e->smblctx,
7466 e->count,
7467 e->offset,
7468 e->brltype,
7469 WINDOWS_LOCK,
7470 blocking_lock,
7471 &status,
7472 &block_smblctx,
7473 NULL);
7475 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7476 /* Windows internal resolution for blocking locks seems
7477 to be about 200ms... Don't wait for less than that. JRA. */
7478 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7479 timeout = lp_lock_spin_time();
7481 defer_lock = true;
7484 /* If a lock sent with timeout of zero would fail, and
7485 * this lock has been requested multiple times,
7486 * according to brl_lock_failed() we convert this
7487 * request to a blocking lock with a timeout of between
7488 * 150 - 300 milliseconds.
7490 * If lp_lock_spin_time() has been set to 0, we skip
7491 * this blocking retry and fail immediately.
7493 * Replacement for do_lock_spin(). JRA. */
7495 if (!req->sconn->using_smb2 &&
7496 br_lck && lp_blocking_locks(SNUM(conn)) &&
7497 lp_lock_spin_time() && !blocking_lock &&
7498 NT_STATUS_EQUAL((status),
7499 NT_STATUS_FILE_LOCK_CONFLICT))
7501 defer_lock = true;
7502 timeout = lp_lock_spin_time();
7505 if (br_lck && defer_lock) {
7507 * A blocking lock was requested. Package up
7508 * this smb into a queued request and push it
7509 * onto the blocking lock queue.
7511 if(push_blocking_lock_request(br_lck,
7512 req,
7513 fsp,
7514 timeout,
7516 e->smblctx,
7517 e->brltype,
7518 WINDOWS_LOCK,
7519 e->offset,
7520 e->count,
7521 block_smblctx)) {
7522 TALLOC_FREE(br_lck);
7523 *async = true;
7524 return NT_STATUS_OK;
7528 TALLOC_FREE(br_lck);
7531 if (!NT_STATUS_IS_OK(status)) {
7532 break;
7536 /* If any of the above locks failed, then we must unlock
7537 all of the previous locks (X/Open spec). */
7539 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7541 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7542 i = -1; /* we want to skip the for loop */
7546 * Ensure we don't do a remove on the lock that just failed,
7547 * as under POSIX rules, if we have a lock already there, we
7548 * will delete it (and we shouldn't) .....
7550 for(i--; i >= 0; i--) {
7551 struct smbd_lock_element *e = &locks[i];
7553 do_unlock(req->sconn->msg_ctx,
7554 fsp,
7555 e->smblctx,
7556 e->count,
7557 e->offset,
7558 WINDOWS_LOCK);
7560 return status;
7563 DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7564 fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7566 return NT_STATUS_OK;
7569 /****************************************************************************
7570 Reply to a lockingX request.
7571 ****************************************************************************/
7573 void reply_lockingX(struct smb_request *req)
7575 connection_struct *conn = req->conn;
7576 files_struct *fsp;
7577 unsigned char locktype;
7578 unsigned char oplocklevel;
7579 uint16 num_ulocks;
7580 uint16 num_locks;
7581 int32 lock_timeout;
7582 int i;
7583 const uint8_t *data;
7584 bool large_file_format;
7585 bool err;
7586 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7587 struct smbd_lock_element *ulocks;
7588 struct smbd_lock_element *locks;
7589 bool async = false;
7591 START_PROFILE(SMBlockingX);
7593 if (req->wct < 8) {
7594 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7595 END_PROFILE(SMBlockingX);
7596 return;
7599 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7600 locktype = CVAL(req->vwv+3, 0);
7601 oplocklevel = CVAL(req->vwv+3, 1);
7602 num_ulocks = SVAL(req->vwv+6, 0);
7603 num_locks = SVAL(req->vwv+7, 0);
7604 lock_timeout = IVAL(req->vwv+4, 0);
7605 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7607 if (!check_fsp(conn, req, fsp)) {
7608 END_PROFILE(SMBlockingX);
7609 return;
7612 data = req->buf;
7614 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7615 /* we don't support these - and CANCEL_LOCK makes w2k
7616 and XP reboot so I don't really want to be
7617 compatible! (tridge) */
7618 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7619 END_PROFILE(SMBlockingX);
7620 return;
7623 /* Check if this is an oplock break on a file
7624 we have granted an oplock on.
7626 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7627 /* Client can insist on breaking to none. */
7628 bool break_to_none = (oplocklevel == 0);
7629 bool result;
7631 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7632 "for fnum = %d\n", (unsigned int)oplocklevel,
7633 fsp->fnum ));
7636 * Make sure we have granted an exclusive or batch oplock on
7637 * this file.
7640 if (fsp->oplock_type == 0) {
7642 /* The Samba4 nbench simulator doesn't understand
7643 the difference between break to level2 and break
7644 to none from level2 - it sends oplock break
7645 replies in both cases. Don't keep logging an error
7646 message here - just ignore it. JRA. */
7648 DEBUG(5,("reply_lockingX: Error : oplock break from "
7649 "client for fnum = %d (oplock=%d) and no "
7650 "oplock granted on this file (%s).\n",
7651 fsp->fnum, fsp->oplock_type,
7652 fsp_str_dbg(fsp)));
7654 /* if this is a pure oplock break request then don't
7655 * send a reply */
7656 if (num_locks == 0 && num_ulocks == 0) {
7657 END_PROFILE(SMBlockingX);
7658 return;
7659 } else {
7660 END_PROFILE(SMBlockingX);
7661 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7662 return;
7666 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7667 (break_to_none)) {
7668 result = remove_oplock(fsp);
7669 } else {
7670 result = downgrade_oplock(fsp);
7673 if (!result) {
7674 DEBUG(0, ("reply_lockingX: error in removing "
7675 "oplock on file %s\n", fsp_str_dbg(fsp)));
7676 /* Hmmm. Is this panic justified? */
7677 smb_panic("internal tdb error");
7680 reply_to_oplock_break_requests(fsp);
7682 /* if this is a pure oplock break request then don't send a
7683 * reply */
7684 if (num_locks == 0 && num_ulocks == 0) {
7685 /* Sanity check - ensure a pure oplock break is not a
7686 chained request. */
7687 if(CVAL(req->vwv+0, 0) != 0xff)
7688 DEBUG(0,("reply_lockingX: Error : pure oplock "
7689 "break is a chained %d request !\n",
7690 (unsigned int)CVAL(req->vwv+0, 0)));
7691 END_PROFILE(SMBlockingX);
7692 return;
7696 if (req->buflen <
7697 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7698 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7699 END_PROFILE(SMBlockingX);
7700 return;
7703 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7704 if (ulocks == NULL) {
7705 reply_nterror(req, NT_STATUS_NO_MEMORY);
7706 END_PROFILE(SMBlockingX);
7707 return;
7710 locks = talloc_array(req, struct smbd_lock_element, num_locks);
7711 if (locks == NULL) {
7712 reply_nterror(req, NT_STATUS_NO_MEMORY);
7713 END_PROFILE(SMBlockingX);
7714 return;
7717 /* Data now points at the beginning of the list
7718 of smb_unlkrng structs */
7719 for(i = 0; i < (int)num_ulocks; i++) {
7720 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
7721 ulocks[i].count = get_lock_count(data, i, large_file_format);
7722 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7723 ulocks[i].brltype = UNLOCK_LOCK;
7726 * There is no error code marked "stupid client bug".... :-).
7728 if(err) {
7729 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7730 END_PROFILE(SMBlockingX);
7731 return;
7735 /* Now do any requested locks */
7736 data += ((large_file_format ? 20 : 10)*num_ulocks);
7738 /* Data now points at the beginning of the list
7739 of smb_lkrng structs */
7741 for(i = 0; i < (int)num_locks; i++) {
7742 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7743 locks[i].count = get_lock_count(data, i, large_file_format);
7744 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7746 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7747 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7748 locks[i].brltype = PENDING_READ_LOCK;
7749 } else {
7750 locks[i].brltype = READ_LOCK;
7752 } else {
7753 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7754 locks[i].brltype = PENDING_WRITE_LOCK;
7755 } else {
7756 locks[i].brltype = WRITE_LOCK;
7761 * There is no error code marked "stupid client bug".... :-).
7763 if(err) {
7764 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7765 END_PROFILE(SMBlockingX);
7766 return;
7770 status = smbd_do_locking(req, fsp,
7771 locktype, lock_timeout,
7772 num_ulocks, ulocks,
7773 num_locks, locks,
7774 &async);
7775 if (!NT_STATUS_IS_OK(status)) {
7776 END_PROFILE(SMBlockingX);
7777 reply_nterror(req, status);
7778 return;
7780 if (async) {
7781 END_PROFILE(SMBlockingX);
7782 return;
7785 reply_outbuf(req, 2, 0);
7787 DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7788 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7790 END_PROFILE(SMBlockingX);
7791 chain_reply(req);
7794 #undef DBGC_CLASS
7795 #define DBGC_CLASS DBGC_ALL
7797 /****************************************************************************
7798 Reply to a SMBreadbmpx (read block multiplex) request.
7799 Always reply with an error, if someone has a platform really needs this,
7800 please contact vl@samba.org
7801 ****************************************************************************/
7803 void reply_readbmpx(struct smb_request *req)
7805 START_PROFILE(SMBreadBmpx);
7806 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7807 END_PROFILE(SMBreadBmpx);
7808 return;
7811 /****************************************************************************
7812 Reply to a SMBreadbs (read block multiplex secondary) request.
7813 Always reply with an error, if someone has a platform really needs this,
7814 please contact vl@samba.org
7815 ****************************************************************************/
7817 void reply_readbs(struct smb_request *req)
7819 START_PROFILE(SMBreadBs);
7820 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7821 END_PROFILE(SMBreadBs);
7822 return;
7825 /****************************************************************************
7826 Reply to a SMBsetattrE.
7827 ****************************************************************************/
7829 void reply_setattrE(struct smb_request *req)
7831 connection_struct *conn = req->conn;
7832 struct smb_file_time ft;
7833 files_struct *fsp;
7834 NTSTATUS status;
7836 START_PROFILE(SMBsetattrE);
7837 ZERO_STRUCT(ft);
7839 if (req->wct < 7) {
7840 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7841 goto out;
7844 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7846 if(!fsp || (fsp->conn != conn)) {
7847 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7848 goto out;
7852 * Convert the DOS times into unix times.
7855 ft.atime = convert_time_t_to_timespec(
7856 srv_make_unix_date2(req->vwv+3));
7857 ft.mtime = convert_time_t_to_timespec(
7858 srv_make_unix_date2(req->vwv+5));
7859 ft.create_time = convert_time_t_to_timespec(
7860 srv_make_unix_date2(req->vwv+1));
7862 reply_outbuf(req, 0, 0);
7865 * Patch from Ray Frush <frush@engr.colostate.edu>
7866 * Sometimes times are sent as zero - ignore them.
7869 /* Ensure we have a valid stat struct for the source. */
7870 status = vfs_stat_fsp(fsp);
7871 if (!NT_STATUS_IS_OK(status)) {
7872 reply_nterror(req, status);
7873 goto out;
7876 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7877 if (!NT_STATUS_IS_OK(status)) {
7878 reply_nterror(req, status);
7879 goto out;
7882 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7883 " createtime=%u\n",
7884 fsp->fnum,
7885 (unsigned int)ft.atime.tv_sec,
7886 (unsigned int)ft.mtime.tv_sec,
7887 (unsigned int)ft.create_time.tv_sec
7889 out:
7890 END_PROFILE(SMBsetattrE);
7891 return;
7895 /* Back from the dead for OS/2..... JRA. */
7897 /****************************************************************************
7898 Reply to a SMBwritebmpx (write block multiplex primary) request.
7899 Always reply with an error, if someone has a platform really needs this,
7900 please contact vl@samba.org
7901 ****************************************************************************/
7903 void reply_writebmpx(struct smb_request *req)
7905 START_PROFILE(SMBwriteBmpx);
7906 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7907 END_PROFILE(SMBwriteBmpx);
7908 return;
7911 /****************************************************************************
7912 Reply to a SMBwritebs (write block multiplex secondary) request.
7913 Always reply with an error, if someone has a platform really needs this,
7914 please contact vl@samba.org
7915 ****************************************************************************/
7917 void reply_writebs(struct smb_request *req)
7919 START_PROFILE(SMBwriteBs);
7920 reply_force_doserror(req, ERRSRV, ERRuseSTD);
7921 END_PROFILE(SMBwriteBs);
7922 return;
7925 /****************************************************************************
7926 Reply to a SMBgetattrE.
7927 ****************************************************************************/
7929 void reply_getattrE(struct smb_request *req)
7931 connection_struct *conn = req->conn;
7932 int mode;
7933 files_struct *fsp;
7934 struct timespec create_ts;
7936 START_PROFILE(SMBgetattrE);
7938 if (req->wct < 1) {
7939 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7940 END_PROFILE(SMBgetattrE);
7941 return;
7944 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7946 if(!fsp || (fsp->conn != conn)) {
7947 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7948 END_PROFILE(SMBgetattrE);
7949 return;
7952 /* Do an fstat on this file */
7953 if(fsp_stat(fsp)) {
7954 reply_nterror(req, map_nt_error_from_unix(errno));
7955 END_PROFILE(SMBgetattrE);
7956 return;
7959 mode = dos_mode(conn, fsp->fsp_name);
7962 * Convert the times into dos times. Set create
7963 * date to be last modify date as UNIX doesn't save
7964 * this.
7967 reply_outbuf(req, 11, 0);
7969 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
7970 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7971 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7972 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
7973 /* Should we check pending modtime here ? JRA */
7974 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7975 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
7977 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
7978 SIVAL(req->outbuf, smb_vwv6, 0);
7979 SIVAL(req->outbuf, smb_vwv8, 0);
7980 } else {
7981 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
7982 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
7983 SIVAL(req->outbuf, smb_vwv8, allocation_size);
7985 SSVAL(req->outbuf,smb_vwv10, mode);
7987 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7989 END_PROFILE(SMBgetattrE);
7990 return;