s3:lib: remove unused sessionid_*() functions
[Samba/gebeck_regimport.git] / source3 / smbd / reply.c
blob4423e8e19091f15217e00b84cee5a3c19cde1de4
1 /*
2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jeremy Allison 1992-2007.
7 Copyright (C) Volker Lendecke 2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
27 #include "includes.h"
28 #include "system/filesys.h"
29 #include "printing.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "fake_file.h"
33 #include "rpc_client/rpc_client.h"
34 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
35 #include "../librpc/gen_ndr/open_files.h"
36 #include "rpc_client/cli_spoolss.h"
37 #include "rpc_client/init_spoolss.h"
38 #include "rpc_server/rpc_ncacn_np.h"
39 #include "libcli/security/security.h"
40 #include "libsmb/nmblib.h"
41 #include "auth.h"
42 #include "smbprofile.h"
43 #include "../lib/tsocket/tsocket.h"
44 #include "lib/tevent_wait.h"
45 #include "libcli/smb/smb_signing.h"
47 /****************************************************************************
48 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
49 path or anything including wildcards.
50 We're assuming here that '/' is not the second byte in any multibyte char
51 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
52 set.
53 ****************************************************************************/
55 /* Custom version for processing POSIX paths. */
56 #define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
58 static NTSTATUS check_path_syntax_internal(char *path,
59 bool posix_path,
60 bool *p_last_component_contains_wcard)
62 char *d = path;
63 const char *s = path;
64 NTSTATUS ret = NT_STATUS_OK;
65 bool start_of_name_component = True;
66 bool stream_started = false;
68 *p_last_component_contains_wcard = False;
70 while (*s) {
71 if (stream_started) {
72 switch (*s) {
73 case '/':
74 case '\\':
75 return NT_STATUS_OBJECT_NAME_INVALID;
76 case ':':
77 if (s[1] == '\0') {
78 return NT_STATUS_OBJECT_NAME_INVALID;
80 if (strchr_m(&s[1], ':')) {
81 return NT_STATUS_OBJECT_NAME_INVALID;
83 break;
87 if ((*s == ':') && !posix_path && !stream_started) {
88 if (*p_last_component_contains_wcard) {
89 return NT_STATUS_OBJECT_NAME_INVALID;
91 /* Stream names allow more characters than file names.
92 We're overloading posix_path here to allow a wider
93 range of characters. If stream_started is true this
94 is still a Windows path even if posix_path is true.
95 JRA.
97 stream_started = true;
98 start_of_name_component = false;
99 posix_path = true;
101 if (s[1] == '\0') {
102 return NT_STATUS_OBJECT_NAME_INVALID;
106 if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
108 * Safe to assume is not the second part of a mb char
109 * as this is handled below.
111 /* Eat multiple '/' or '\\' */
112 while (IS_PATH_SEP(*s,posix_path)) {
113 s++;
115 if ((d != path) && (*s != '\0')) {
116 /* We only care about non-leading or trailing '/' or '\\' */
117 *d++ = '/';
120 start_of_name_component = True;
121 /* New component. */
122 *p_last_component_contains_wcard = False;
123 continue;
126 if (start_of_name_component) {
127 if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
128 /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
131 * No mb char starts with '.' so we're safe checking the directory separator here.
134 /* If we just added a '/' - delete it */
135 if ((d > path) && (*(d-1) == '/')) {
136 *(d-1) = '\0';
137 d--;
140 /* Are we at the start ? Can't go back further if so. */
141 if (d <= path) {
142 ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
143 break;
145 /* Go back one level... */
146 /* We know this is safe as '/' cannot be part of a mb sequence. */
147 /* NOTE - if this assumption is invalid we are not in good shape... */
148 /* Decrement d first as d points to the *next* char to write into. */
149 for (d--; d > path; d--) {
150 if (*d == '/')
151 break;
153 s += 2; /* Else go past the .. */
154 /* We're still at the start of a name component, just the previous one. */
155 continue;
157 } else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
158 if (posix_path) {
159 /* Eat the '.' */
160 s++;
161 continue;
167 if (!(*s & 0x80)) {
168 if (!posix_path) {
169 if (*s <= 0x1f || *s == '|') {
170 return NT_STATUS_OBJECT_NAME_INVALID;
172 switch (*s) {
173 case '*':
174 case '?':
175 case '<':
176 case '>':
177 case '"':
178 *p_last_component_contains_wcard = True;
179 break;
180 default:
181 break;
184 *d++ = *s++;
185 } else {
186 size_t siz;
187 /* Get the size of the next MB character. */
188 next_codepoint(s,&siz);
189 switch(siz) {
190 case 5:
191 *d++ = *s++;
192 /*fall through*/
193 case 4:
194 *d++ = *s++;
195 /*fall through*/
196 case 3:
197 *d++ = *s++;
198 /*fall through*/
199 case 2:
200 *d++ = *s++;
201 /*fall through*/
202 case 1:
203 *d++ = *s++;
204 break;
205 default:
206 DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
207 *d = '\0';
208 return NT_STATUS_INVALID_PARAMETER;
211 start_of_name_component = False;
214 *d = '\0';
216 return ret;
219 /****************************************************************************
220 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
221 No wildcards allowed.
222 ****************************************************************************/
224 NTSTATUS check_path_syntax(char *path)
226 bool ignore;
227 return check_path_syntax_internal(path, False, &ignore);
230 /****************************************************************************
231 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
232 Wildcards allowed - p_contains_wcard returns true if the last component contained
233 a wildcard.
234 ****************************************************************************/
236 NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
238 return check_path_syntax_internal(path, False, p_contains_wcard);
241 /****************************************************************************
242 Check the path for a POSIX client.
243 We're assuming here that '/' is not the second byte in any multibyte char
244 set (a safe assumption).
245 ****************************************************************************/
247 NTSTATUS check_path_syntax_posix(char *path)
249 bool ignore;
250 return check_path_syntax_internal(path, True, &ignore);
253 /****************************************************************************
254 Pull a string and check the path allowing a wilcard - provide for error return.
255 ****************************************************************************/
257 size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
258 const char *base_ptr,
259 uint16 smb_flags2,
260 char **pp_dest,
261 const char *src,
262 size_t src_len,
263 int flags,
264 NTSTATUS *err,
265 bool *contains_wcard)
267 size_t ret;
269 *pp_dest = NULL;
271 ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
272 src_len, flags);
274 if (!*pp_dest) {
275 *err = NT_STATUS_INVALID_PARAMETER;
276 return ret;
279 *contains_wcard = False;
281 if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
283 * For a DFS path the function parse_dfs_path()
284 * will do the path processing, just make a copy.
286 *err = NT_STATUS_OK;
287 return ret;
290 if (lp_posix_pathnames()) {
291 *err = check_path_syntax_posix(*pp_dest);
292 } else {
293 *err = check_path_syntax_wcard(*pp_dest, contains_wcard);
296 return ret;
299 /****************************************************************************
300 Pull a string and check the path - provide for error return.
301 ****************************************************************************/
303 size_t srvstr_get_path(TALLOC_CTX *ctx,
304 const char *base_ptr,
305 uint16 smb_flags2,
306 char **pp_dest,
307 const char *src,
308 size_t src_len,
309 int flags,
310 NTSTATUS *err)
312 bool ignore;
313 return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
314 src_len, flags, err, &ignore);
317 size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
318 char **pp_dest, const char *src, int flags,
319 NTSTATUS *err, bool *contains_wcard)
321 return srvstr_get_path_wcard(mem_ctx, (const char *)req->inbuf, req->flags2,
322 pp_dest, src, smbreq_bufrem(req, src),
323 flags, err, contains_wcard);
326 size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
327 char **pp_dest, const char *src, int flags,
328 NTSTATUS *err)
330 bool ignore;
331 return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
332 flags, err, &ignore);
335 /****************************************************************************
336 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
337 ****************************************************************************/
339 bool check_fsp_open(connection_struct *conn, struct smb_request *req,
340 files_struct *fsp)
342 if ((fsp == NULL) || (conn == NULL)) {
343 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
344 return False;
346 if ((conn != fsp->conn) || (req->vuid != fsp->vuid)) {
347 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
348 return False;
350 return True;
353 /****************************************************************************
354 Check if we have a correct fsp pointing to a file.
355 ****************************************************************************/
357 bool check_fsp(connection_struct *conn, struct smb_request *req,
358 files_struct *fsp)
360 if (!check_fsp_open(conn, req, fsp)) {
361 return False;
363 if (fsp->is_directory) {
364 reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
365 return False;
367 if (fsp->fh->fd == -1) {
368 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
369 return False;
371 fsp->num_smb_operations++;
372 return True;
375 /****************************************************************************
376 Check if we have a correct fsp pointing to a quota fake file. Replacement for
377 the CHECK_NTQUOTA_HANDLE_OK macro.
378 ****************************************************************************/
380 bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
381 files_struct *fsp)
383 if (!check_fsp_open(conn, req, fsp)) {
384 return false;
387 if (fsp->is_directory) {
388 return false;
391 if (fsp->fake_file_handle == NULL) {
392 return false;
395 if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
396 return false;
399 if (fsp->fake_file_handle->private_data == NULL) {
400 return false;
403 return true;
406 static bool netbios_session_retarget(struct smbd_server_connection *sconn,
407 const char *name, int name_type)
409 char *trim_name;
410 char *trim_name_type;
411 const char *retarget_parm;
412 char *retarget;
413 char *p;
414 int retarget_type = 0x20;
415 int retarget_port = NBT_SMB_PORT;
416 struct sockaddr_storage retarget_addr;
417 struct sockaddr_in *in_addr;
418 bool ret = false;
419 uint8_t outbuf[10];
421 if (get_socket_port(sconn->sock) != NBT_SMB_PORT) {
422 return false;
425 trim_name = talloc_strdup(talloc_tos(), name);
426 if (trim_name == NULL) {
427 goto fail;
429 trim_char(trim_name, ' ', ' ');
431 trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
432 name_type);
433 if (trim_name_type == NULL) {
434 goto fail;
437 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
438 trim_name_type, NULL);
439 if (retarget_parm == NULL) {
440 retarget_parm = lp_parm_const_string(-1, "netbios retarget",
441 trim_name, NULL);
443 if (retarget_parm == NULL) {
444 goto fail;
447 retarget = talloc_strdup(trim_name, retarget_parm);
448 if (retarget == NULL) {
449 goto fail;
452 DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
454 p = strchr(retarget, ':');
455 if (p != NULL) {
456 *p++ = '\0';
457 retarget_port = atoi(p);
460 p = strchr_m(retarget, '#');
461 if (p != NULL) {
462 *p++ = '\0';
463 if (sscanf(p, "%x", &retarget_type) != 1) {
464 goto fail;
468 ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
469 if (!ret) {
470 DEBUG(10, ("could not resolve %s\n", retarget));
471 goto fail;
474 if (retarget_addr.ss_family != AF_INET) {
475 DEBUG(10, ("Retarget target not an IPv4 addr\n"));
476 goto fail;
479 in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
481 _smb_setlen(outbuf, 6);
482 SCVAL(outbuf, 0, 0x84);
483 *(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
484 *(uint16_t *)(outbuf+8) = htons(retarget_port);
486 if (!srv_send_smb(sconn, (char *)outbuf, false, 0, false,
487 NULL)) {
488 exit_server_cleanly("netbios_session_retarget: srv_send_smb "
489 "failed.");
492 ret = true;
493 fail:
494 TALLOC_FREE(trim_name);
495 return ret;
498 static void reply_called_name_not_present(char *outbuf)
500 smb_setlen(outbuf, 1);
501 SCVAL(outbuf, 0, 0x83);
502 SCVAL(outbuf, 4, 0x82);
505 /****************************************************************************
506 Reply to a (netbios-level) special message.
507 ****************************************************************************/
509 void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inbuf_size)
511 int msg_type = CVAL(inbuf,0);
512 int msg_flags = CVAL(inbuf,1);
514 * We only really use 4 bytes of the outbuf, but for the smb_setlen
515 * calculation & friends (srv_send_smb uses that) we need the full smb
516 * header.
518 char outbuf[smb_size];
520 memset(outbuf, '\0', sizeof(outbuf));
522 smb_setlen(outbuf,0);
524 switch (msg_type) {
525 case NBSSrequest: /* session request */
527 /* inbuf_size is guarenteed to be at least 4. */
528 fstring name1,name2;
529 int name_type1, name_type2;
530 int name_len1, name_len2;
532 *name1 = *name2 = 0;
534 if (sconn->nbt.got_session) {
535 exit_server_cleanly("multiple session request not permitted");
538 SCVAL(outbuf,0,NBSSpositive);
539 SCVAL(outbuf,3,0);
541 /* inbuf_size is guaranteed to be at least 4. */
542 name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
543 if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
544 DEBUG(0,("Invalid name length in session request\n"));
545 reply_called_name_not_present(outbuf);
546 break;
548 name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
549 if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
550 DEBUG(0,("Invalid name length in session request\n"));
551 reply_called_name_not_present(outbuf);
552 break;
555 name_type1 = name_extract((unsigned char *)inbuf,
556 inbuf_size,(unsigned int)4,name1);
557 name_type2 = name_extract((unsigned char *)inbuf,
558 inbuf_size,(unsigned int)(4 + name_len1),name2);
560 if (name_type1 == -1 || name_type2 == -1) {
561 DEBUG(0,("Invalid name type in session request\n"));
562 reply_called_name_not_present(outbuf);
563 break;
566 DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
567 name1, name_type1, name2, name_type2));
569 if (netbios_session_retarget(sconn, name1, name_type1)) {
570 exit_server_cleanly("retargeted client");
574 * Windows NT/2k uses "*SMBSERVER" and XP uses
575 * "*SMBSERV" arrggg!!!
577 if (strequal(name1, "*SMBSERVER ")
578 || strequal(name1, "*SMBSERV ")) {
579 char *raddr;
581 raddr = tsocket_address_inet_addr_string(sconn->remote_address,
582 talloc_tos());
583 if (raddr == NULL) {
584 exit_server_cleanly("could not allocate raddr");
587 fstrcpy(name1, raddr);
590 set_local_machine_name(name1, True);
591 set_remote_machine_name(name2, True);
593 if (is_ipaddress(sconn->remote_hostname)) {
594 char *p = discard_const_p(char, sconn->remote_hostname);
596 talloc_free(p);
598 sconn->remote_hostname = talloc_strdup(sconn,
599 get_remote_machine_name());
600 if (sconn->remote_hostname == NULL) {
601 exit_server_cleanly("could not copy remote name");
603 sconn->conn->remote_hostname = sconn->remote_hostname;
606 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
607 get_local_machine_name(), get_remote_machine_name(),
608 name_type2));
610 if (name_type2 == 'R') {
611 /* We are being asked for a pathworks session ---
612 no thanks! */
613 reply_called_name_not_present(outbuf);
614 break;
617 reload_services(sconn, conn_snum_used, true);
618 reopen_logs();
620 sconn->nbt.got_session = true;
621 break;
624 case 0x89: /* session keepalive request
625 (some old clients produce this?) */
626 SCVAL(outbuf,0,NBSSkeepalive);
627 SCVAL(outbuf,3,0);
628 break;
630 case NBSSpositive: /* positive session response */
631 case NBSSnegative: /* negative session response */
632 case NBSSretarget: /* retarget session response */
633 DEBUG(0,("Unexpected session response\n"));
634 break;
636 case NBSSkeepalive: /* session keepalive */
637 default:
638 return;
641 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
642 msg_type, msg_flags));
644 srv_send_smb(sconn, outbuf, false, 0, false, NULL);
646 if (CVAL(outbuf, 0) != 0x82) {
647 exit_server_cleanly("invalid netbios session");
649 return;
652 /****************************************************************************
653 Reply to a tcon.
654 conn POINTER CAN BE NULL HERE !
655 ****************************************************************************/
657 void reply_tcon(struct smb_request *req)
659 connection_struct *conn = req->conn;
660 const char *service;
661 char *service_buf = NULL;
662 char *password = NULL;
663 char *dev = NULL;
664 int pwlen=0;
665 NTSTATUS nt_status;
666 const char *p;
667 TALLOC_CTX *ctx = talloc_tos();
668 struct smbd_server_connection *sconn = req->sconn;
670 START_PROFILE(SMBtcon);
672 if (req->buflen < 4) {
673 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
674 END_PROFILE(SMBtcon);
675 return;
678 p = (const char *)req->buf + 1;
679 p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
680 p += 1;
681 pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
682 p += pwlen+1;
683 p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
684 p += 1;
686 if (service_buf == NULL || password == NULL || dev == NULL) {
687 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
688 END_PROFILE(SMBtcon);
689 return;
691 p = strrchr_m(service_buf,'\\');
692 if (p) {
693 service = p+1;
694 } else {
695 service = service_buf;
698 conn = make_connection(sconn,service,dev,
699 req->vuid,&nt_status);
700 req->conn = conn;
702 if (!conn) {
703 reply_nterror(req, nt_status);
704 END_PROFILE(SMBtcon);
705 return;
708 reply_outbuf(req, 2, 0);
709 SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
710 SSVAL(req->outbuf,smb_vwv1,conn->cnum);
711 SSVAL(req->outbuf,smb_tid,conn->cnum);
713 DEBUG(3,("tcon service=%s cnum=%d\n",
714 service, conn->cnum));
716 END_PROFILE(SMBtcon);
717 return;
720 /****************************************************************************
721 Reply to a tcon and X.
722 conn POINTER CAN BE NULL HERE !
723 ****************************************************************************/
725 void reply_tcon_and_X(struct smb_request *req)
727 connection_struct *conn = req->conn;
728 const char *service = NULL;
729 TALLOC_CTX *ctx = talloc_tos();
730 /* what the cleint thinks the device is */
731 char *client_devicetype = NULL;
732 /* what the server tells the client the share represents */
733 const char *server_devicetype;
734 NTSTATUS nt_status;
735 int passlen;
736 char *path = NULL;
737 const char *p, *q;
738 uint16_t tcon_flags;
739 struct smbXsrv_session *session = NULL;
740 NTTIME now = timeval_to_nttime(&req->request_time);
741 bool session_key_updated = false;
742 uint16_t optional_support = 0;
743 struct smbd_server_connection *sconn = req->sconn;
745 START_PROFILE(SMBtconX);
747 if (req->wct < 4) {
748 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
749 END_PROFILE(SMBtconX);
750 return;
753 passlen = SVAL(req->vwv+3, 0);
754 tcon_flags = SVAL(req->vwv+2, 0);
756 /* we might have to close an old one */
757 if ((tcon_flags & TCONX_FLAG_DISCONNECT_TID) && conn) {
758 struct smbXsrv_tcon *tcon;
759 NTSTATUS status;
761 tcon = conn->tcon;
762 req->conn = NULL;
763 conn = NULL;
766 * TODO: cancel all outstanding requests on the tcon
768 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
769 if (!NT_STATUS_IS_OK(status)) {
770 DEBUG(0, ("reply_tcon_and_X: "
771 "smbXsrv_tcon_disconnect() failed: %s\n",
772 nt_errstr(status)));
774 * If we hit this case, there is something completely
775 * wrong, so we better disconnect the transport connection.
777 END_PROFILE(SMBtconX);
778 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
779 return;
782 TALLOC_FREE(tcon);
785 if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
786 reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
787 END_PROFILE(SMBtconX);
788 return;
791 if (sconn->smb1.negprot.encrypted_passwords) {
792 p = (const char *)req->buf + passlen;
793 } else {
794 p = (const char *)req->buf + passlen + 1;
797 p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
799 if (path == NULL) {
800 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
801 END_PROFILE(SMBtconX);
802 return;
806 * the service name can be either: \\server\share
807 * or share directly like on the DELL PowerVault 705
809 if (*path=='\\') {
810 q = strchr_m(path+2,'\\');
811 if (!q) {
812 reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
813 END_PROFILE(SMBtconX);
814 return;
816 service = q+1;
817 } else {
818 service = path;
821 p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
822 &client_devicetype, p,
823 MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
825 if (client_devicetype == NULL) {
826 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
827 END_PROFILE(SMBtconX);
828 return;
831 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
833 nt_status = smb1srv_session_lookup(req->sconn->conn,
834 req->vuid, now, &session);
835 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_USER_SESSION_DELETED)) {
836 reply_force_doserror(req, ERRSRV, ERRbaduid);
837 END_PROFILE(SMBtconX);
838 return;
840 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
841 reply_nterror(req, nt_status);
842 END_PROFILE(SMBtconX);
843 return;
845 if (!NT_STATUS_IS_OK(nt_status)) {
846 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
847 END_PROFILE(SMBtconX);
848 return;
851 if (session->global->auth_session_info == NULL) {
852 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
853 END_PROFILE(SMBtconX);
854 return;
858 * If there is no application key defined yet
859 * we create one.
861 * This means we setup the application key on the
862 * first tcon that happens via the given session.
864 * Once the application key is defined, it does not
865 * change any more.
867 if (session->global->application_key.length == 0 &&
868 session->global->signing_key.length > 0)
870 struct smbXsrv_session *x = session;
871 struct auth_session_info *session_info =
872 session->global->auth_session_info;
873 uint8_t session_key[16];
875 ZERO_STRUCT(session_key);
876 memcpy(session_key, x->global->signing_key.data,
877 MIN(x->global->signing_key.length, sizeof(session_key)));
880 * The application key is truncated/padded to 16 bytes
882 x->global->application_key = data_blob_talloc(x->global,
883 session_key,
884 sizeof(session_key));
885 ZERO_STRUCT(session_key);
886 if (x->global->application_key.data == NULL) {
887 reply_nterror(req, NT_STATUS_NO_MEMORY);
888 END_PROFILE(SMBtconX);
889 return;
892 if (tcon_flags & TCONX_FLAG_EXTENDED_SIGNATURES) {
893 smb_key_derivation(x->global->application_key.data,
894 x->global->application_key.length,
895 x->global->application_key.data);
896 optional_support |= SMB_EXTENDED_SIGNATURES;
900 * Place the application key into the session_info
902 data_blob_clear_free(&session_info->session_key);
903 session_info->session_key = data_blob_dup_talloc(session_info,
904 x->global->application_key);
905 if (session_info->session_key.data == NULL) {
906 data_blob_clear_free(&x->global->application_key);
907 reply_nterror(req, NT_STATUS_NO_MEMORY);
908 END_PROFILE(SMBtconX);
909 return;
911 session_key_updated = true;
914 conn = make_connection(sconn, service, client_devicetype,
915 req->vuid, &nt_status);
916 req->conn =conn;
918 if (!conn) {
919 if (session_key_updated) {
920 struct smbXsrv_session *x = session;
921 struct auth_session_info *session_info =
922 session->global->auth_session_info;
923 data_blob_clear_free(&x->global->application_key);
924 data_blob_clear_free(&session_info->session_key);
926 reply_nterror(req, nt_status);
927 END_PROFILE(SMBtconX);
928 return;
931 if ( IS_IPC(conn) )
932 server_devicetype = "IPC";
933 else if ( IS_PRINT(conn) )
934 server_devicetype = "LPT1:";
935 else
936 server_devicetype = "A:";
938 if (get_Protocol() < PROTOCOL_NT1) {
939 reply_outbuf(req, 2, 0);
940 if (message_push_string(&req->outbuf, server_devicetype,
941 STR_TERMINATE|STR_ASCII) == -1) {
942 reply_nterror(req, NT_STATUS_NO_MEMORY);
943 END_PROFILE(SMBtconX);
944 return;
946 } else {
947 /* NT sets the fstype of IPC$ to the null string */
948 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(ctx, SNUM(conn));
950 if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
951 /* Return permissions. */
952 uint32 perm1 = 0;
953 uint32 perm2 = 0;
955 reply_outbuf(req, 7, 0);
957 if (IS_IPC(conn)) {
958 perm1 = FILE_ALL_ACCESS;
959 perm2 = FILE_ALL_ACCESS;
960 } else {
961 perm1 = conn->share_access;
964 SIVAL(req->outbuf, smb_vwv3, perm1);
965 SIVAL(req->outbuf, smb_vwv5, perm2);
966 } else {
967 reply_outbuf(req, 3, 0);
970 if ((message_push_string(&req->outbuf, server_devicetype,
971 STR_TERMINATE|STR_ASCII) == -1)
972 || (message_push_string(&req->outbuf, fstype,
973 STR_TERMINATE) == -1)) {
974 reply_nterror(req, NT_STATUS_NO_MEMORY);
975 END_PROFILE(SMBtconX);
976 return;
979 /* what does setting this bit do? It is set by NT4 and
980 may affect the ability to autorun mounted cdroms */
981 optional_support |= SMB_SUPPORT_SEARCH_BITS;
982 optional_support |=
983 (lp_csc_policy(SNUM(conn)) << SMB_CSC_POLICY_SHIFT);
985 if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
986 DEBUG(2,("Serving %s as a Dfs root\n",
987 lp_servicename(ctx, SNUM(conn)) ));
988 optional_support |= SMB_SHARE_IN_DFS;
991 SSVAL(req->outbuf, smb_vwv2, optional_support);
994 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
995 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
997 DEBUG(3,("tconX service=%s \n",
998 service));
1000 /* set the incoming and outgoing tid to the just created one */
1001 SSVAL(discard_const_p(uint8_t, req->inbuf),smb_tid,conn->cnum);
1002 SSVAL(req->outbuf,smb_tid,conn->cnum);
1004 END_PROFILE(SMBtconX);
1006 req->tid = conn->cnum;
1009 /****************************************************************************
1010 Reply to an unknown type.
1011 ****************************************************************************/
1013 void reply_unknown_new(struct smb_request *req, uint8 type)
1015 DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
1016 smb_fn_name(type), type, type));
1017 reply_force_doserror(req, ERRSRV, ERRunknownsmb);
1018 return;
1021 /****************************************************************************
1022 Reply to an ioctl.
1023 conn POINTER CAN BE NULL HERE !
1024 ****************************************************************************/
1026 void reply_ioctl(struct smb_request *req)
1028 connection_struct *conn = req->conn;
1029 uint16 device;
1030 uint16 function;
1031 uint32 ioctl_code;
1032 int replysize;
1033 char *p;
1035 START_PROFILE(SMBioctl);
1037 if (req->wct < 3) {
1038 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1039 END_PROFILE(SMBioctl);
1040 return;
1043 device = SVAL(req->vwv+1, 0);
1044 function = SVAL(req->vwv+2, 0);
1045 ioctl_code = (device << 16) + function;
1047 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
1049 switch (ioctl_code) {
1050 case IOCTL_QUERY_JOB_INFO:
1051 replysize = 32;
1052 break;
1053 default:
1054 reply_force_doserror(req, ERRSRV, ERRnosupport);
1055 END_PROFILE(SMBioctl);
1056 return;
1059 reply_outbuf(req, 8, replysize+1);
1060 SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
1061 SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
1062 SSVAL(req->outbuf,smb_vwv6,52); /* Offset to data */
1063 p = smb_buf(req->outbuf);
1064 memset(p, '\0', replysize+1); /* valgrind-safe. */
1065 p += 1; /* Allow for alignment */
1067 switch (ioctl_code) {
1068 case IOCTL_QUERY_JOB_INFO:
1070 files_struct *fsp = file_fsp(
1071 req, SVAL(req->vwv+0, 0));
1072 if (!fsp) {
1073 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
1074 END_PROFILE(SMBioctl);
1075 return;
1077 /* Job number */
1078 SSVAL(p, 0, print_spool_rap_jobid(fsp->print_file));
1080 srvstr_push((char *)req->outbuf, req->flags2, p+2,
1081 lp_netbios_name(), 15,
1082 STR_TERMINATE|STR_ASCII);
1083 if (conn) {
1084 srvstr_push((char *)req->outbuf, req->flags2,
1085 p+18,
1086 lp_servicename(talloc_tos(),
1087 SNUM(conn)),
1088 13, STR_TERMINATE|STR_ASCII);
1089 } else {
1090 memset(p+18, 0, 13);
1092 break;
1096 END_PROFILE(SMBioctl);
1097 return;
1100 /****************************************************************************
1101 Strange checkpath NTSTATUS mapping.
1102 ****************************************************************************/
1104 static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
1106 /* Strange DOS error code semantics only for checkpath... */
1107 if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
1108 if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
1109 /* We need to map to ERRbadpath */
1110 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
1113 return status;
1116 /****************************************************************************
1117 Reply to a checkpath.
1118 ****************************************************************************/
1120 void reply_checkpath(struct smb_request *req)
1122 connection_struct *conn = req->conn;
1123 struct smb_filename *smb_fname = NULL;
1124 char *name = NULL;
1125 NTSTATUS status;
1126 TALLOC_CTX *ctx = talloc_tos();
1128 START_PROFILE(SMBcheckpath);
1130 srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
1131 STR_TERMINATE, &status);
1133 if (!NT_STATUS_IS_OK(status)) {
1134 status = map_checkpath_error(req->flags2, status);
1135 reply_nterror(req, status);
1136 END_PROFILE(SMBcheckpath);
1137 return;
1140 DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1142 status = filename_convert(ctx,
1143 conn,
1144 req->flags2 & FLAGS2_DFS_PATHNAMES,
1145 name,
1147 NULL,
1148 &smb_fname);
1150 if (!NT_STATUS_IS_OK(status)) {
1151 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1152 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1153 ERRSRV, ERRbadpath);
1154 END_PROFILE(SMBcheckpath);
1155 return;
1157 goto path_err;
1160 if (!VALID_STAT(smb_fname->st) &&
1161 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1162 DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1163 smb_fname_str_dbg(smb_fname), strerror(errno)));
1164 status = map_nt_error_from_unix(errno);
1165 goto path_err;
1168 if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1169 reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1170 ERRDOS, ERRbadpath);
1171 goto out;
1174 reply_outbuf(req, 0, 0);
1176 path_err:
1177 /* We special case this - as when a Windows machine
1178 is parsing a path is steps through the components
1179 one at a time - if a component fails it expects
1180 ERRbadpath, not ERRbadfile.
1182 status = map_checkpath_error(req->flags2, status);
1183 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1185 * Windows returns different error codes if
1186 * the parent directory is valid but not the
1187 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1188 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1189 * if the path is invalid.
1191 reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1192 ERRDOS, ERRbadpath);
1193 goto out;
1196 reply_nterror(req, status);
1198 out:
1199 TALLOC_FREE(smb_fname);
1200 END_PROFILE(SMBcheckpath);
1201 return;
1204 /****************************************************************************
1205 Reply to a getatr.
1206 ****************************************************************************/
1208 void reply_getatr(struct smb_request *req)
1210 connection_struct *conn = req->conn;
1211 struct smb_filename *smb_fname = NULL;
1212 char *fname = NULL;
1213 int mode=0;
1214 off_t size=0;
1215 time_t mtime=0;
1216 const char *p;
1217 NTSTATUS status;
1218 TALLOC_CTX *ctx = talloc_tos();
1219 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1221 START_PROFILE(SMBgetatr);
1223 p = (const char *)req->buf + 1;
1224 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1225 if (!NT_STATUS_IS_OK(status)) {
1226 reply_nterror(req, status);
1227 goto out;
1230 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1231 under WfWg - weird! */
1232 if (*fname == '\0') {
1233 mode = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
1234 if (!CAN_WRITE(conn)) {
1235 mode |= FILE_ATTRIBUTE_READONLY;
1237 size = 0;
1238 mtime = 0;
1239 } else {
1240 status = filename_convert(ctx,
1241 conn,
1242 req->flags2 & FLAGS2_DFS_PATHNAMES,
1243 fname,
1245 NULL,
1246 &smb_fname);
1247 if (!NT_STATUS_IS_OK(status)) {
1248 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1249 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1250 ERRSRV, ERRbadpath);
1251 goto out;
1253 reply_nterror(req, status);
1254 goto out;
1256 if (!VALID_STAT(smb_fname->st) &&
1257 (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1258 DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1259 smb_fname_str_dbg(smb_fname),
1260 strerror(errno)));
1261 reply_nterror(req, map_nt_error_from_unix(errno));
1262 goto out;
1265 mode = dos_mode(conn, smb_fname);
1266 size = smb_fname->st.st_ex_size;
1268 if (ask_sharemode) {
1269 struct timespec write_time_ts;
1270 struct file_id fileid;
1272 ZERO_STRUCT(write_time_ts);
1273 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1274 get_file_infos(fileid, 0, NULL, &write_time_ts);
1275 if (!null_timespec(write_time_ts)) {
1276 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1280 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1281 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
1282 size = 0;
1286 reply_outbuf(req, 10, 0);
1288 SSVAL(req->outbuf,smb_vwv0,mode);
1289 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1290 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1291 } else {
1292 srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1294 SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1296 if (get_Protocol() >= PROTOCOL_NT1) {
1297 SSVAL(req->outbuf, smb_flg2,
1298 SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1301 DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1302 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1304 out:
1305 TALLOC_FREE(smb_fname);
1306 TALLOC_FREE(fname);
1307 END_PROFILE(SMBgetatr);
1308 return;
1311 /****************************************************************************
1312 Reply to a setatr.
1313 ****************************************************************************/
1315 void reply_setatr(struct smb_request *req)
1317 struct smb_file_time ft;
1318 connection_struct *conn = req->conn;
1319 struct smb_filename *smb_fname = NULL;
1320 char *fname = NULL;
1321 int mode;
1322 time_t mtime;
1323 const char *p;
1324 NTSTATUS status;
1325 TALLOC_CTX *ctx = talloc_tos();
1327 START_PROFILE(SMBsetatr);
1329 ZERO_STRUCT(ft);
1331 if (req->wct < 2) {
1332 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1333 goto out;
1336 p = (const char *)req->buf + 1;
1337 p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1338 if (!NT_STATUS_IS_OK(status)) {
1339 reply_nterror(req, status);
1340 goto out;
1343 status = filename_convert(ctx,
1344 conn,
1345 req->flags2 & FLAGS2_DFS_PATHNAMES,
1346 fname,
1348 NULL,
1349 &smb_fname);
1350 if (!NT_STATUS_IS_OK(status)) {
1351 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1352 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1353 ERRSRV, ERRbadpath);
1354 goto out;
1356 reply_nterror(req, status);
1357 goto out;
1360 if (smb_fname->base_name[0] == '.' &&
1361 smb_fname->base_name[1] == '\0') {
1363 * Not sure here is the right place to catch this
1364 * condition. Might be moved to somewhere else later -- vl
1366 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1367 goto out;
1370 mode = SVAL(req->vwv+0, 0);
1371 mtime = srv_make_unix_date3(req->vwv+1);
1373 if (mode != FILE_ATTRIBUTE_NORMAL) {
1374 if (VALID_STAT_OF_DIR(smb_fname->st))
1375 mode |= FILE_ATTRIBUTE_DIRECTORY;
1376 else
1377 mode &= ~FILE_ATTRIBUTE_DIRECTORY;
1379 status = check_access(conn, NULL, smb_fname,
1380 FILE_WRITE_ATTRIBUTES);
1381 if (!NT_STATUS_IS_OK(status)) {
1382 reply_nterror(req, status);
1383 goto out;
1386 if (file_set_dosmode(conn, smb_fname, mode, NULL,
1387 false) != 0) {
1388 reply_nterror(req, map_nt_error_from_unix(errno));
1389 goto out;
1393 ft.mtime = convert_time_t_to_timespec(mtime);
1394 status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1395 if (!NT_STATUS_IS_OK(status)) {
1396 reply_nterror(req, status);
1397 goto out;
1400 reply_outbuf(req, 0, 0);
1402 DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1403 mode));
1404 out:
1405 TALLOC_FREE(smb_fname);
1406 END_PROFILE(SMBsetatr);
1407 return;
1410 /****************************************************************************
1411 Reply to a dskattr.
1412 ****************************************************************************/
1414 void reply_dskattr(struct smb_request *req)
1416 connection_struct *conn = req->conn;
1417 uint64_t dfree,dsize,bsize;
1418 START_PROFILE(SMBdskattr);
1420 if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1421 reply_nterror(req, map_nt_error_from_unix(errno));
1422 END_PROFILE(SMBdskattr);
1423 return;
1426 reply_outbuf(req, 5, 0);
1428 if (get_Protocol() <= PROTOCOL_LANMAN2) {
1429 double total_space, free_space;
1430 /* we need to scale this to a number that DOS6 can handle. We
1431 use floating point so we can handle large drives on systems
1432 that don't have 64 bit integers
1434 we end up displaying a maximum of 2G to DOS systems
1436 total_space = dsize * (double)bsize;
1437 free_space = dfree * (double)bsize;
1439 dsize = (uint64_t)((total_space+63*512) / (64*512));
1440 dfree = (uint64_t)((free_space+63*512) / (64*512));
1442 if (dsize > 0xFFFF) dsize = 0xFFFF;
1443 if (dfree > 0xFFFF) dfree = 0xFFFF;
1445 SSVAL(req->outbuf,smb_vwv0,dsize);
1446 SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1447 SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1448 SSVAL(req->outbuf,smb_vwv3,dfree);
1449 } else {
1450 SSVAL(req->outbuf,smb_vwv0,dsize);
1451 SSVAL(req->outbuf,smb_vwv1,bsize/512);
1452 SSVAL(req->outbuf,smb_vwv2,512);
1453 SSVAL(req->outbuf,smb_vwv3,dfree);
1456 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1458 END_PROFILE(SMBdskattr);
1459 return;
1463 * Utility function to split the filename from the directory.
1465 static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1466 char **fname_dir_out,
1467 char **fname_mask_out)
1469 const char *p = NULL;
1470 char *fname_dir = NULL;
1471 char *fname_mask = NULL;
1473 p = strrchr_m(fname_in, '/');
1474 if (!p) {
1475 fname_dir = talloc_strdup(ctx, ".");
1476 fname_mask = talloc_strdup(ctx, fname_in);
1477 } else {
1478 fname_dir = talloc_strndup(ctx, fname_in,
1479 PTR_DIFF(p, fname_in));
1480 fname_mask = talloc_strdup(ctx, p+1);
1483 if (!fname_dir || !fname_mask) {
1484 TALLOC_FREE(fname_dir);
1485 TALLOC_FREE(fname_mask);
1486 return NT_STATUS_NO_MEMORY;
1489 *fname_dir_out = fname_dir;
1490 *fname_mask_out = fname_mask;
1491 return NT_STATUS_OK;
1494 /****************************************************************************
1495 Reply to a search.
1496 Can be called from SMBsearch, SMBffirst or SMBfunique.
1497 ****************************************************************************/
1499 void reply_search(struct smb_request *req)
1501 connection_struct *conn = req->conn;
1502 char *path = NULL;
1503 const char *mask = NULL;
1504 char *directory = NULL;
1505 struct smb_filename *smb_fname = NULL;
1506 char *fname = NULL;
1507 off_t size;
1508 uint32 mode;
1509 struct timespec date;
1510 uint32 dirtype;
1511 unsigned int numentries = 0;
1512 unsigned int maxentries = 0;
1513 bool finished = False;
1514 const char *p;
1515 int status_len;
1516 char status[21];
1517 int dptr_num= -1;
1518 bool check_descend = False;
1519 bool expect_close = False;
1520 NTSTATUS nt_status;
1521 bool mask_contains_wcard = False;
1522 bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1523 TALLOC_CTX *ctx = talloc_tos();
1524 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1525 struct dptr_struct *dirptr = NULL;
1526 struct smbd_server_connection *sconn = req->sconn;
1528 START_PROFILE(SMBsearch);
1530 if (req->wct < 2) {
1531 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1532 goto out;
1535 if (lp_posix_pathnames()) {
1536 reply_unknown_new(req, req->cmd);
1537 goto out;
1540 /* If we were called as SMBffirst then we must expect close. */
1541 if(req->cmd == SMBffirst) {
1542 expect_close = True;
1545 reply_outbuf(req, 1, 3);
1546 maxentries = SVAL(req->vwv+0, 0);
1547 dirtype = SVAL(req->vwv+1, 0);
1548 p = (const char *)req->buf + 1;
1549 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1550 &nt_status, &mask_contains_wcard);
1551 if (!NT_STATUS_IS_OK(nt_status)) {
1552 reply_nterror(req, nt_status);
1553 goto out;
1556 p++;
1557 status_len = SVAL(p, 0);
1558 p += 2;
1560 /* dirtype &= ~FILE_ATTRIBUTE_DIRECTORY; */
1562 if (status_len == 0) {
1563 nt_status = filename_convert(ctx, conn,
1564 req->flags2 & FLAGS2_DFS_PATHNAMES,
1565 path,
1566 UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1567 &mask_contains_wcard,
1568 &smb_fname);
1569 if (!NT_STATUS_IS_OK(nt_status)) {
1570 if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1571 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1572 ERRSRV, ERRbadpath);
1573 goto out;
1575 reply_nterror(req, nt_status);
1576 goto out;
1579 directory = smb_fname->base_name;
1581 p = strrchr_m(directory,'/');
1582 if ((p != NULL) && (*directory != '/')) {
1583 mask = p + 1;
1584 directory = talloc_strndup(ctx, directory,
1585 PTR_DIFF(p, directory));
1586 } else {
1587 mask = directory;
1588 directory = talloc_strdup(ctx,".");
1591 if (!directory) {
1592 reply_nterror(req, NT_STATUS_NO_MEMORY);
1593 goto out;
1596 memset((char *)status,'\0',21);
1597 SCVAL(status,0,(dirtype & 0x1F));
1599 nt_status = dptr_create(conn,
1600 NULL, /* req */
1601 NULL, /* fsp */
1602 directory,
1603 True,
1604 expect_close,
1605 req->smbpid,
1606 mask,
1607 mask_contains_wcard,
1608 dirtype,
1609 &dirptr);
1610 if (!NT_STATUS_IS_OK(nt_status)) {
1611 reply_nterror(req, nt_status);
1612 goto out;
1614 dptr_num = dptr_dnum(dirptr);
1615 } else {
1616 int status_dirtype;
1617 const char *dirpath;
1619 memcpy(status,p,21);
1620 status_dirtype = CVAL(status,0) & 0x1F;
1621 if (status_dirtype != (dirtype & 0x1F)) {
1622 dirtype = status_dirtype;
1625 dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1626 if (!dirptr) {
1627 goto SearchEmpty;
1629 dirpath = dptr_path(sconn, dptr_num);
1630 directory = talloc_strdup(ctx, dirpath);
1631 if (!directory) {
1632 reply_nterror(req, NT_STATUS_NO_MEMORY);
1633 goto out;
1636 mask = dptr_wcard(sconn, dptr_num);
1637 if (!mask) {
1638 goto SearchEmpty;
1641 * For a 'continue' search we have no string. So
1642 * check from the initial saved string.
1644 mask_contains_wcard = ms_has_wild(mask);
1645 dirtype = dptr_attr(sconn, dptr_num);
1648 DEBUG(4,("dptr_num is %d\n",dptr_num));
1650 /* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1651 dptr_init_search_op(dirptr);
1653 if ((dirtype&0x1F) == FILE_ATTRIBUTE_VOLUME) {
1654 char buf[DIR_STRUCT_SIZE];
1655 memcpy(buf,status,21);
1656 if (!make_dir_struct(ctx,buf,"???????????",volume_label(ctx, SNUM(conn)),
1657 0,FILE_ATTRIBUTE_VOLUME,0,!allow_long_path_components)) {
1658 reply_nterror(req, NT_STATUS_NO_MEMORY);
1659 goto out;
1661 dptr_fill(sconn, buf+12,dptr_num);
1662 if (dptr_zero(buf+12) && (status_len==0)) {
1663 numentries = 1;
1664 } else {
1665 numentries = 0;
1667 if (message_push_blob(&req->outbuf,
1668 data_blob_const(buf, sizeof(buf)))
1669 == -1) {
1670 reply_nterror(req, NT_STATUS_NO_MEMORY);
1671 goto out;
1673 } else {
1674 unsigned int i;
1675 maxentries = MIN(
1676 maxentries,
1677 ((BUFFER_SIZE -
1678 ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1679 /DIR_STRUCT_SIZE));
1681 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1682 directory,lp_dontdescend(ctx, SNUM(conn))));
1683 if (in_list(directory, lp_dontdescend(ctx, SNUM(conn)),True)) {
1684 check_descend = True;
1687 for (i=numentries;(i<maxentries) && !finished;i++) {
1688 finished = !get_dir_entry(ctx,
1689 dirptr,
1690 mask,
1691 dirtype,
1692 &fname,
1693 &size,
1694 &mode,
1695 &date,
1696 check_descend,
1697 ask_sharemode);
1698 if (!finished) {
1699 char buf[DIR_STRUCT_SIZE];
1700 memcpy(buf,status,21);
1701 if (!make_dir_struct(ctx,
1702 buf,
1703 mask,
1704 fname,
1705 size,
1706 mode,
1707 convert_timespec_to_time_t(date),
1708 !allow_long_path_components)) {
1709 reply_nterror(req, NT_STATUS_NO_MEMORY);
1710 goto out;
1712 if (!dptr_fill(sconn, buf+12,dptr_num)) {
1713 break;
1715 if (message_push_blob(&req->outbuf,
1716 data_blob_const(buf, sizeof(buf)))
1717 == -1) {
1718 reply_nterror(req, NT_STATUS_NO_MEMORY);
1719 goto out;
1721 numentries++;
1726 SearchEmpty:
1728 /* If we were called as SMBffirst with smb_search_id == NULL
1729 and no entries were found then return error and close dirptr
1730 (X/Open spec) */
1732 if (numentries == 0) {
1733 dptr_close(sconn, &dptr_num);
1734 } else if(expect_close && status_len == 0) {
1735 /* Close the dptr - we know it's gone */
1736 dptr_close(sconn, &dptr_num);
1739 /* If we were called as SMBfunique, then we can close the dirptr now ! */
1740 if(dptr_num >= 0 && req->cmd == SMBfunique) {
1741 dptr_close(sconn, &dptr_num);
1744 if ((numentries == 0) && !mask_contains_wcard) {
1745 reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1746 goto out;
1749 SSVAL(req->outbuf,smb_vwv0,numentries);
1750 SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1751 SCVAL(smb_buf(req->outbuf),0,5);
1752 SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1754 /* The replies here are never long name. */
1755 SSVAL(req->outbuf, smb_flg2,
1756 SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1757 if (!allow_long_path_components) {
1758 SSVAL(req->outbuf, smb_flg2,
1759 SVAL(req->outbuf, smb_flg2)
1760 & (~FLAGS2_LONG_PATH_COMPONENTS));
1763 /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1764 SSVAL(req->outbuf, smb_flg2,
1765 (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1767 DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1768 smb_fn_name(req->cmd),
1769 mask,
1770 directory,
1771 dirtype,
1772 numentries,
1773 maxentries ));
1774 out:
1775 TALLOC_FREE(directory);
1776 TALLOC_FREE(smb_fname);
1777 END_PROFILE(SMBsearch);
1778 return;
1781 /****************************************************************************
1782 Reply to a fclose (stop directory search).
1783 ****************************************************************************/
1785 void reply_fclose(struct smb_request *req)
1787 int status_len;
1788 char status[21];
1789 int dptr_num= -2;
1790 const char *p;
1791 char *path = NULL;
1792 NTSTATUS err;
1793 bool path_contains_wcard = False;
1794 TALLOC_CTX *ctx = talloc_tos();
1795 struct smbd_server_connection *sconn = req->sconn;
1797 START_PROFILE(SMBfclose);
1799 if (lp_posix_pathnames()) {
1800 reply_unknown_new(req, req->cmd);
1801 END_PROFILE(SMBfclose);
1802 return;
1805 p = (const char *)req->buf + 1;
1806 p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1807 &err, &path_contains_wcard);
1808 if (!NT_STATUS_IS_OK(err)) {
1809 reply_nterror(req, err);
1810 END_PROFILE(SMBfclose);
1811 return;
1813 p++;
1814 status_len = SVAL(p,0);
1815 p += 2;
1817 if (status_len == 0) {
1818 reply_force_doserror(req, ERRSRV, ERRsrverror);
1819 END_PROFILE(SMBfclose);
1820 return;
1823 memcpy(status,p,21);
1825 if(dptr_fetch(sconn, status+12,&dptr_num)) {
1826 /* Close the dptr - we know it's gone */
1827 dptr_close(sconn, &dptr_num);
1830 reply_outbuf(req, 1, 0);
1831 SSVAL(req->outbuf,smb_vwv0,0);
1833 DEBUG(3,("search close\n"));
1835 END_PROFILE(SMBfclose);
1836 return;
1839 /****************************************************************************
1840 Reply to an open.
1841 ****************************************************************************/
1843 void reply_open(struct smb_request *req)
1845 connection_struct *conn = req->conn;
1846 struct smb_filename *smb_fname = NULL;
1847 char *fname = NULL;
1848 uint32 fattr=0;
1849 off_t size = 0;
1850 time_t mtime=0;
1851 int info;
1852 files_struct *fsp;
1853 int oplock_request;
1854 int deny_mode;
1855 uint32 dos_attr;
1856 uint32 access_mask;
1857 uint32 share_mode;
1858 uint32 create_disposition;
1859 uint32 create_options = 0;
1860 uint32_t private_flags = 0;
1861 NTSTATUS status;
1862 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1863 TALLOC_CTX *ctx = talloc_tos();
1865 START_PROFILE(SMBopen);
1867 if (req->wct < 2) {
1868 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1869 goto out;
1872 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1873 deny_mode = SVAL(req->vwv+0, 0);
1874 dos_attr = SVAL(req->vwv+1, 0);
1876 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1877 STR_TERMINATE, &status);
1878 if (!NT_STATUS_IS_OK(status)) {
1879 reply_nterror(req, status);
1880 goto out;
1883 status = filename_convert(ctx,
1884 conn,
1885 req->flags2 & FLAGS2_DFS_PATHNAMES,
1886 fname,
1888 NULL,
1889 &smb_fname);
1890 if (!NT_STATUS_IS_OK(status)) {
1891 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1892 reply_botherror(req,
1893 NT_STATUS_PATH_NOT_COVERED,
1894 ERRSRV, ERRbadpath);
1895 goto out;
1897 reply_nterror(req, status);
1898 goto out;
1901 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1902 OPENX_FILE_EXISTS_OPEN, &access_mask,
1903 &share_mode, &create_disposition,
1904 &create_options, &private_flags)) {
1905 reply_force_doserror(req, ERRDOS, ERRbadaccess);
1906 goto out;
1909 status = SMB_VFS_CREATE_FILE(
1910 conn, /* conn */
1911 req, /* req */
1912 0, /* root_dir_fid */
1913 smb_fname, /* fname */
1914 access_mask, /* access_mask */
1915 share_mode, /* share_access */
1916 create_disposition, /* create_disposition*/
1917 create_options, /* create_options */
1918 dos_attr, /* file_attributes */
1919 oplock_request, /* oplock_request */
1920 0, /* allocation_size */
1921 private_flags,
1922 NULL, /* sd */
1923 NULL, /* ea_list */
1924 &fsp, /* result */
1925 &info); /* pinfo */
1927 if (!NT_STATUS_IS_OK(status)) {
1928 if (open_was_deferred(req->sconn, req->mid)) {
1929 /* We have re-scheduled this call. */
1930 goto out;
1932 reply_openerror(req, status);
1933 goto out;
1936 size = smb_fname->st.st_ex_size;
1937 fattr = dos_mode(conn, smb_fname);
1939 /* Deal with other possible opens having a modified
1940 write time. JRA. */
1941 if (ask_sharemode) {
1942 struct timespec write_time_ts;
1944 ZERO_STRUCT(write_time_ts);
1945 get_file_infos(fsp->file_id, 0, NULL, &write_time_ts);
1946 if (!null_timespec(write_time_ts)) {
1947 update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1951 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1953 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1954 DEBUG(3,("attempt to open a directory %s\n",
1955 fsp_str_dbg(fsp)));
1956 close_file(req, fsp, ERROR_CLOSE);
1957 reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1958 ERRDOS, ERRnoaccess);
1959 goto out;
1962 reply_outbuf(req, 7, 0);
1963 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1964 SSVAL(req->outbuf,smb_vwv1,fattr);
1965 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1966 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1967 } else {
1968 srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1970 SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1971 SSVAL(req->outbuf,smb_vwv6,deny_mode);
1973 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1974 SCVAL(req->outbuf,smb_flg,
1975 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1978 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1979 SCVAL(req->outbuf,smb_flg,
1980 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1982 out:
1983 TALLOC_FREE(smb_fname);
1984 END_PROFILE(SMBopen);
1985 return;
1988 /****************************************************************************
1989 Reply to an open and X.
1990 ****************************************************************************/
1992 void reply_open_and_X(struct smb_request *req)
1994 connection_struct *conn = req->conn;
1995 struct smb_filename *smb_fname = NULL;
1996 char *fname = NULL;
1997 uint16 open_flags;
1998 int deny_mode;
1999 uint32 smb_attr;
2000 /* Breakout the oplock request bits so we can set the
2001 reply bits separately. */
2002 int ex_oplock_request;
2003 int core_oplock_request;
2004 int oplock_request;
2005 #if 0
2006 int smb_sattr = SVAL(req->vwv+4, 0);
2007 uint32 smb_time = make_unix_date3(req->vwv+6);
2008 #endif
2009 int smb_ofun;
2010 uint32 fattr=0;
2011 int mtime=0;
2012 int smb_action = 0;
2013 files_struct *fsp;
2014 NTSTATUS status;
2015 uint64_t allocation_size;
2016 ssize_t retval = -1;
2017 uint32 access_mask;
2018 uint32 share_mode;
2019 uint32 create_disposition;
2020 uint32 create_options = 0;
2021 uint32_t private_flags = 0;
2022 TALLOC_CTX *ctx = talloc_tos();
2024 START_PROFILE(SMBopenX);
2026 if (req->wct < 15) {
2027 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2028 goto out;
2031 open_flags = SVAL(req->vwv+2, 0);
2032 deny_mode = SVAL(req->vwv+3, 0);
2033 smb_attr = SVAL(req->vwv+5, 0);
2034 ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
2035 core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2036 oplock_request = ex_oplock_request | core_oplock_request;
2037 smb_ofun = SVAL(req->vwv+8, 0);
2038 allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
2040 /* If it's an IPC, pass off the pipe handler. */
2041 if (IS_IPC(conn)) {
2042 if (lp_nt_pipe_support()) {
2043 reply_open_pipe_and_X(conn, req);
2044 } else {
2045 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
2047 goto out;
2050 /* XXXX we need to handle passed times, sattr and flags */
2051 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
2052 STR_TERMINATE, &status);
2053 if (!NT_STATUS_IS_OK(status)) {
2054 reply_nterror(req, status);
2055 goto out;
2058 status = filename_convert(ctx,
2059 conn,
2060 req->flags2 & FLAGS2_DFS_PATHNAMES,
2061 fname,
2063 NULL,
2064 &smb_fname);
2065 if (!NT_STATUS_IS_OK(status)) {
2066 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2067 reply_botherror(req,
2068 NT_STATUS_PATH_NOT_COVERED,
2069 ERRSRV, ERRbadpath);
2070 goto out;
2072 reply_nterror(req, status);
2073 goto out;
2076 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
2077 smb_ofun,
2078 &access_mask, &share_mode,
2079 &create_disposition,
2080 &create_options,
2081 &private_flags)) {
2082 reply_force_doserror(req, ERRDOS, ERRbadaccess);
2083 goto out;
2086 status = SMB_VFS_CREATE_FILE(
2087 conn, /* conn */
2088 req, /* req */
2089 0, /* root_dir_fid */
2090 smb_fname, /* fname */
2091 access_mask, /* access_mask */
2092 share_mode, /* share_access */
2093 create_disposition, /* create_disposition*/
2094 create_options, /* create_options */
2095 smb_attr, /* file_attributes */
2096 oplock_request, /* oplock_request */
2097 0, /* allocation_size */
2098 private_flags,
2099 NULL, /* sd */
2100 NULL, /* ea_list */
2101 &fsp, /* result */
2102 &smb_action); /* pinfo */
2104 if (!NT_STATUS_IS_OK(status)) {
2105 if (open_was_deferred(req->sconn, req->mid)) {
2106 /* We have re-scheduled this call. */
2107 goto out;
2109 reply_openerror(req, status);
2110 goto out;
2113 /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
2114 if the file is truncated or created. */
2115 if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
2116 fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
2117 if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
2118 close_file(req, fsp, ERROR_CLOSE);
2119 reply_nterror(req, NT_STATUS_DISK_FULL);
2120 goto out;
2122 retval = vfs_set_filelen(fsp, (off_t)allocation_size);
2123 if (retval < 0) {
2124 close_file(req, fsp, ERROR_CLOSE);
2125 reply_nterror(req, NT_STATUS_DISK_FULL);
2126 goto out;
2128 status = vfs_stat_fsp(fsp);
2129 if (!NT_STATUS_IS_OK(status)) {
2130 close_file(req, fsp, ERROR_CLOSE);
2131 reply_nterror(req, status);
2132 goto out;
2136 fattr = dos_mode(conn, fsp->fsp_name);
2137 mtime = convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime);
2138 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2139 close_file(req, fsp, ERROR_CLOSE);
2140 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2141 goto out;
2144 /* If the caller set the extended oplock request bit
2145 and we granted one (by whatever means) - set the
2146 correct bit for extended oplock reply.
2149 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2150 smb_action |= EXTENDED_OPLOCK_GRANTED;
2153 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2154 smb_action |= EXTENDED_OPLOCK_GRANTED;
2157 /* If the caller set the core oplock request bit
2158 and we granted one (by whatever means) - set the
2159 correct bit for core oplock reply.
2162 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2163 reply_outbuf(req, 19, 0);
2164 } else {
2165 reply_outbuf(req, 15, 0);
2168 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2169 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2171 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2172 SCVAL(req->outbuf, smb_flg,
2173 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2176 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2177 SCVAL(req->outbuf, smb_flg,
2178 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2181 SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2182 SSVAL(req->outbuf,smb_vwv3,fattr);
2183 if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2184 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2185 } else {
2186 srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2188 SIVAL(req->outbuf,smb_vwv6,(uint32)fsp->fsp_name->st.st_ex_size);
2189 SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2190 SSVAL(req->outbuf,smb_vwv11,smb_action);
2192 if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2193 SIVAL(req->outbuf, smb_vwv15, SEC_STD_ALL);
2196 out:
2197 TALLOC_FREE(smb_fname);
2198 END_PROFILE(SMBopenX);
2199 return;
2202 /****************************************************************************
2203 Reply to a SMBulogoffX.
2204 ****************************************************************************/
2206 void reply_ulogoffX(struct smb_request *req)
2208 struct smbd_server_connection *sconn = req->sconn;
2209 struct user_struct *vuser;
2210 struct smbXsrv_session *session = NULL;
2211 NTSTATUS status;
2213 START_PROFILE(SMBulogoffX);
2215 vuser = get_valid_user_struct(sconn, req->vuid);
2217 if(vuser == NULL) {
2218 DEBUG(3,("ulogoff, vuser id %llu does not map to user.\n",
2219 (unsigned long long)req->vuid));
2221 req->vuid = UID_FIELD_INVALID;
2222 reply_force_doserror(req, ERRSRV, ERRbaduid);
2223 END_PROFILE(SMBulogoffX);
2224 return;
2227 session = vuser->session;
2228 vuser = NULL;
2231 * TODO: cancel all outstanding requests on the session
2233 status = smbXsrv_session_logoff(session);
2234 if (!NT_STATUS_IS_OK(status)) {
2235 DEBUG(0, ("reply_ulogoff: "
2236 "smbXsrv_session_logoff() failed: %s\n",
2237 nt_errstr(status)));
2239 * If we hit this case, there is something completely
2240 * wrong, so we better disconnect the transport connection.
2242 END_PROFILE(SMBulogoffX);
2243 exit_server(__location__ ": smbXsrv_session_logoff failed");
2244 return;
2247 TALLOC_FREE(session);
2249 reply_outbuf(req, 2, 0);
2250 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
2251 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
2253 DEBUG(3, ("ulogoffX vuid=%llu\n",
2254 (unsigned long long)req->vuid));
2256 END_PROFILE(SMBulogoffX);
2257 req->vuid = UID_FIELD_INVALID;
2260 /****************************************************************************
2261 Reply to a mknew or a create.
2262 ****************************************************************************/
2264 void reply_mknew(struct smb_request *req)
2266 connection_struct *conn = req->conn;
2267 struct smb_filename *smb_fname = NULL;
2268 char *fname = NULL;
2269 uint32 fattr = 0;
2270 struct smb_file_time ft;
2271 files_struct *fsp;
2272 int oplock_request = 0;
2273 NTSTATUS status;
2274 uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2275 uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2276 uint32 create_disposition;
2277 uint32 create_options = 0;
2278 TALLOC_CTX *ctx = talloc_tos();
2280 START_PROFILE(SMBcreate);
2281 ZERO_STRUCT(ft);
2283 if (req->wct < 3) {
2284 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2285 goto out;
2288 fattr = SVAL(req->vwv+0, 0);
2289 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2291 /* mtime. */
2292 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2294 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2295 STR_TERMINATE, &status);
2296 if (!NT_STATUS_IS_OK(status)) {
2297 reply_nterror(req, status);
2298 goto out;
2301 status = filename_convert(ctx,
2302 conn,
2303 req->flags2 & FLAGS2_DFS_PATHNAMES,
2304 fname,
2306 NULL,
2307 &smb_fname);
2308 if (!NT_STATUS_IS_OK(status)) {
2309 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2310 reply_botherror(req,
2311 NT_STATUS_PATH_NOT_COVERED,
2312 ERRSRV, ERRbadpath);
2313 goto out;
2315 reply_nterror(req, status);
2316 goto out;
2319 if (fattr & FILE_ATTRIBUTE_VOLUME) {
2320 DEBUG(0,("Attempt to create file (%s) with volid set - "
2321 "please report this\n",
2322 smb_fname_str_dbg(smb_fname)));
2325 if(req->cmd == SMBmknew) {
2326 /* We should fail if file exists. */
2327 create_disposition = FILE_CREATE;
2328 } else {
2329 /* Create if file doesn't exist, truncate if it does. */
2330 create_disposition = FILE_OVERWRITE_IF;
2333 status = SMB_VFS_CREATE_FILE(
2334 conn, /* conn */
2335 req, /* req */
2336 0, /* root_dir_fid */
2337 smb_fname, /* fname */
2338 access_mask, /* access_mask */
2339 share_mode, /* share_access */
2340 create_disposition, /* create_disposition*/
2341 create_options, /* create_options */
2342 fattr, /* file_attributes */
2343 oplock_request, /* oplock_request */
2344 0, /* allocation_size */
2345 0, /* private_flags */
2346 NULL, /* sd */
2347 NULL, /* ea_list */
2348 &fsp, /* result */
2349 NULL); /* pinfo */
2351 if (!NT_STATUS_IS_OK(status)) {
2352 if (open_was_deferred(req->sconn, req->mid)) {
2353 /* We have re-scheduled this call. */
2354 goto out;
2356 reply_openerror(req, status);
2357 goto out;
2360 ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2361 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2362 if (!NT_STATUS_IS_OK(status)) {
2363 END_PROFILE(SMBcreate);
2364 goto out;
2367 reply_outbuf(req, 1, 0);
2368 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2370 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2371 SCVAL(req->outbuf,smb_flg,
2372 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2375 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2376 SCVAL(req->outbuf,smb_flg,
2377 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2380 DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2381 DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2382 smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2383 (unsigned int)fattr));
2385 out:
2386 TALLOC_FREE(smb_fname);
2387 END_PROFILE(SMBcreate);
2388 return;
2391 /****************************************************************************
2392 Reply to a create temporary file.
2393 ****************************************************************************/
2395 void reply_ctemp(struct smb_request *req)
2397 connection_struct *conn = req->conn;
2398 struct smb_filename *smb_fname = NULL;
2399 char *fname = NULL;
2400 uint32 fattr;
2401 files_struct *fsp;
2402 int oplock_request;
2403 int tmpfd;
2404 char *s;
2405 NTSTATUS status;
2406 TALLOC_CTX *ctx = talloc_tos();
2408 START_PROFILE(SMBctemp);
2410 if (req->wct < 3) {
2411 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2412 goto out;
2415 fattr = SVAL(req->vwv+0, 0);
2416 oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2418 srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2419 STR_TERMINATE, &status);
2420 if (!NT_STATUS_IS_OK(status)) {
2421 reply_nterror(req, status);
2422 goto out;
2424 if (*fname) {
2425 fname = talloc_asprintf(ctx,
2426 "%s/TMXXXXXX",
2427 fname);
2428 } else {
2429 fname = talloc_strdup(ctx, "TMXXXXXX");
2432 if (!fname) {
2433 reply_nterror(req, NT_STATUS_NO_MEMORY);
2434 goto out;
2437 status = filename_convert(ctx, conn,
2438 req->flags2 & FLAGS2_DFS_PATHNAMES,
2439 fname,
2441 NULL,
2442 &smb_fname);
2443 if (!NT_STATUS_IS_OK(status)) {
2444 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2445 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2446 ERRSRV, ERRbadpath);
2447 goto out;
2449 reply_nterror(req, status);
2450 goto out;
2453 tmpfd = mkstemp(smb_fname->base_name);
2454 if (tmpfd == -1) {
2455 reply_nterror(req, map_nt_error_from_unix(errno));
2456 goto out;
2459 SMB_VFS_STAT(conn, smb_fname);
2461 /* We should fail if file does not exist. */
2462 status = SMB_VFS_CREATE_FILE(
2463 conn, /* conn */
2464 req, /* req */
2465 0, /* root_dir_fid */
2466 smb_fname, /* fname */
2467 FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2468 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
2469 FILE_OPEN, /* create_disposition*/
2470 0, /* create_options */
2471 fattr, /* file_attributes */
2472 oplock_request, /* oplock_request */
2473 0, /* allocation_size */
2474 0, /* private_flags */
2475 NULL, /* sd */
2476 NULL, /* ea_list */
2477 &fsp, /* result */
2478 NULL); /* pinfo */
2480 /* close fd from mkstemp() */
2481 close(tmpfd);
2483 if (!NT_STATUS_IS_OK(status)) {
2484 if (open_was_deferred(req->sconn, req->mid)) {
2485 /* We have re-scheduled this call. */
2486 goto out;
2488 reply_openerror(req, status);
2489 goto out;
2492 reply_outbuf(req, 1, 0);
2493 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2495 /* the returned filename is relative to the directory */
2496 s = strrchr_m(fsp->fsp_name->base_name, '/');
2497 if (!s) {
2498 s = fsp->fsp_name->base_name;
2499 } else {
2500 s++;
2503 #if 0
2504 /* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2505 thing in the byte section. JRA */
2506 SSVALS(p, 0, -1); /* what is this? not in spec */
2507 #endif
2508 if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2509 == -1) {
2510 reply_nterror(req, NT_STATUS_NO_MEMORY);
2511 goto out;
2514 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2515 SCVAL(req->outbuf, smb_flg,
2516 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2519 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2520 SCVAL(req->outbuf, smb_flg,
2521 CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2524 DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2525 DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2526 fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2527 out:
2528 TALLOC_FREE(smb_fname);
2529 END_PROFILE(SMBctemp);
2530 return;
2533 /*******************************************************************
2534 Check if a user is allowed to rename a file.
2535 ********************************************************************/
2537 static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2538 uint16 dirtype)
2540 if (!CAN_WRITE(conn)) {
2541 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2544 if ((dirtype & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) !=
2545 (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2546 /* Only bother to read the DOS attribute if we might deny the
2547 rename on the grounds of attribute missmatch. */
2548 uint32_t fmode = dos_mode(conn, fsp->fsp_name);
2549 if ((fmode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) {
2550 return NT_STATUS_NO_SUCH_FILE;
2554 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2555 if (fsp->posix_open) {
2556 return NT_STATUS_OK;
2559 /* If no pathnames are open below this
2560 directory, allow the rename. */
2562 if (file_find_subpath(fsp)) {
2563 return NT_STATUS_ACCESS_DENIED;
2565 return NT_STATUS_OK;
2568 if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2569 return NT_STATUS_OK;
2572 return NT_STATUS_ACCESS_DENIED;
2575 /*******************************************************************
2576 * unlink a file with all relevant access checks
2577 *******************************************************************/
2579 static NTSTATUS do_unlink(connection_struct *conn,
2580 struct smb_request *req,
2581 struct smb_filename *smb_fname,
2582 uint32 dirtype)
2584 uint32 fattr;
2585 files_struct *fsp;
2586 uint32 dirtype_orig = dirtype;
2587 NTSTATUS status;
2588 int ret;
2589 bool posix_paths = lp_posix_pathnames();
2591 DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2592 smb_fname_str_dbg(smb_fname),
2593 dirtype));
2595 if (!CAN_WRITE(conn)) {
2596 return NT_STATUS_MEDIA_WRITE_PROTECTED;
2599 if (posix_paths) {
2600 ret = SMB_VFS_LSTAT(conn, smb_fname);
2601 } else {
2602 ret = SMB_VFS_STAT(conn, smb_fname);
2604 if (ret != 0) {
2605 return map_nt_error_from_unix(errno);
2608 fattr = dos_mode(conn, smb_fname);
2610 if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2611 dirtype = FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY;
2614 dirtype &= (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
2615 if (!dirtype) {
2616 return NT_STATUS_NO_SUCH_FILE;
2619 if (!dir_check_ftype(conn, fattr, dirtype)) {
2620 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2621 return NT_STATUS_FILE_IS_A_DIRECTORY;
2623 return NT_STATUS_NO_SUCH_FILE;
2626 if (dirtype_orig & 0x8000) {
2627 /* These will never be set for POSIX. */
2628 return NT_STATUS_NO_SUCH_FILE;
2631 #if 0
2632 if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2633 return NT_STATUS_FILE_IS_A_DIRECTORY;
2636 if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2637 return NT_STATUS_NO_SUCH_FILE;
2640 if (dirtype & 0xFF00) {
2641 /* These will never be set for POSIX. */
2642 return NT_STATUS_NO_SUCH_FILE;
2645 dirtype &= 0xFF;
2646 if (!dirtype) {
2647 return NT_STATUS_NO_SUCH_FILE;
2650 /* Can't delete a directory. */
2651 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
2652 return NT_STATUS_FILE_IS_A_DIRECTORY;
2654 #endif
2656 #if 0 /* JRATEST */
2657 else if (dirtype & FILE_ATTRIBUTE_DIRECTORY) /* Asked for a directory and it isn't. */
2658 return NT_STATUS_OBJECT_NAME_INVALID;
2659 #endif /* JRATEST */
2661 /* On open checks the open itself will check the share mode, so
2662 don't do it here as we'll get it wrong. */
2664 status = SMB_VFS_CREATE_FILE
2665 (conn, /* conn */
2666 req, /* req */
2667 0, /* root_dir_fid */
2668 smb_fname, /* fname */
2669 DELETE_ACCESS, /* access_mask */
2670 FILE_SHARE_NONE, /* share_access */
2671 FILE_OPEN, /* create_disposition*/
2672 FILE_NON_DIRECTORY_FILE, /* create_options */
2673 /* file_attributes */
2674 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2675 FILE_ATTRIBUTE_NORMAL,
2676 0, /* oplock_request */
2677 0, /* allocation_size */
2678 0, /* private_flags */
2679 NULL, /* sd */
2680 NULL, /* ea_list */
2681 &fsp, /* result */
2682 NULL); /* pinfo */
2684 if (!NT_STATUS_IS_OK(status)) {
2685 DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2686 nt_errstr(status)));
2687 return status;
2690 status = can_set_delete_on_close(fsp, fattr);
2691 if (!NT_STATUS_IS_OK(status)) {
2692 DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2693 "(%s)\n",
2694 smb_fname_str_dbg(smb_fname),
2695 nt_errstr(status)));
2696 close_file(req, fsp, NORMAL_CLOSE);
2697 return status;
2700 /* The set is across all open files on this dev/inode pair. */
2701 if (!set_delete_on_close(fsp, True,
2702 conn->session_info->security_token,
2703 conn->session_info->unix_token)) {
2704 close_file(req, fsp, NORMAL_CLOSE);
2705 return NT_STATUS_ACCESS_DENIED;
2708 return close_file(req, fsp, NORMAL_CLOSE);
2711 /****************************************************************************
2712 The guts of the unlink command, split out so it may be called by the NT SMB
2713 code.
2714 ****************************************************************************/
2716 NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2717 uint32 dirtype, struct smb_filename *smb_fname,
2718 bool has_wild)
2720 char *fname_dir = NULL;
2721 char *fname_mask = NULL;
2722 int count=0;
2723 NTSTATUS status = NT_STATUS_OK;
2724 TALLOC_CTX *ctx = talloc_tos();
2726 /* Split up the directory from the filename/mask. */
2727 status = split_fname_dir_mask(ctx, smb_fname->base_name,
2728 &fname_dir, &fname_mask);
2729 if (!NT_STATUS_IS_OK(status)) {
2730 goto out;
2734 * We should only check the mangled cache
2735 * here if unix_convert failed. This means
2736 * that the path in 'mask' doesn't exist
2737 * on the file system and so we need to look
2738 * for a possible mangle. This patch from
2739 * Tine Smukavec <valentin.smukavec@hermes.si>.
2742 if (!VALID_STAT(smb_fname->st) &&
2743 mangle_is_mangled(fname_mask, conn->params)) {
2744 char *new_mask = NULL;
2745 mangle_lookup_name_from_8_3(ctx, fname_mask,
2746 &new_mask, conn->params);
2747 if (new_mask) {
2748 TALLOC_FREE(fname_mask);
2749 fname_mask = new_mask;
2753 if (!has_wild) {
2756 * Only one file needs to be unlinked. Append the mask back
2757 * onto the directory.
2759 TALLOC_FREE(smb_fname->base_name);
2760 if (ISDOT(fname_dir)) {
2761 /* Ensure we use canonical names on open. */
2762 smb_fname->base_name = talloc_asprintf(smb_fname,
2763 "%s",
2764 fname_mask);
2765 } else {
2766 smb_fname->base_name = talloc_asprintf(smb_fname,
2767 "%s/%s",
2768 fname_dir,
2769 fname_mask);
2771 if (!smb_fname->base_name) {
2772 status = NT_STATUS_NO_MEMORY;
2773 goto out;
2775 if (dirtype == 0) {
2776 dirtype = FILE_ATTRIBUTE_NORMAL;
2779 status = check_name(conn, smb_fname->base_name);
2780 if (!NT_STATUS_IS_OK(status)) {
2781 goto out;
2784 status = do_unlink(conn, req, smb_fname, dirtype);
2785 if (!NT_STATUS_IS_OK(status)) {
2786 goto out;
2789 count++;
2790 } else {
2791 struct smb_Dir *dir_hnd = NULL;
2792 long offset = 0;
2793 const char *dname = NULL;
2794 char *talloced = NULL;
2796 if ((dirtype & SAMBA_ATTRIBUTES_MASK) == FILE_ATTRIBUTE_DIRECTORY) {
2797 status = NT_STATUS_OBJECT_NAME_INVALID;
2798 goto out;
2801 if (strequal(fname_mask,"????????.???")) {
2802 TALLOC_FREE(fname_mask);
2803 fname_mask = talloc_strdup(ctx, "*");
2804 if (!fname_mask) {
2805 status = NT_STATUS_NO_MEMORY;
2806 goto out;
2810 status = check_name(conn, fname_dir);
2811 if (!NT_STATUS_IS_OK(status)) {
2812 goto out;
2815 dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2816 dirtype);
2817 if (dir_hnd == NULL) {
2818 status = map_nt_error_from_unix(errno);
2819 goto out;
2822 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2823 the pattern matches against the long name, otherwise the short name
2824 We don't implement this yet XXXX
2827 status = NT_STATUS_NO_SUCH_FILE;
2829 while ((dname = ReadDirName(dir_hnd, &offset,
2830 &smb_fname->st, &talloced))) {
2831 TALLOC_CTX *frame = talloc_stackframe();
2833 if (!is_visible_file(conn, fname_dir, dname,
2834 &smb_fname->st, true)) {
2835 TALLOC_FREE(frame);
2836 TALLOC_FREE(talloced);
2837 continue;
2840 /* Quick check for "." and ".." */
2841 if (ISDOT(dname) || ISDOTDOT(dname)) {
2842 TALLOC_FREE(frame);
2843 TALLOC_FREE(talloced);
2844 continue;
2847 if(!mask_match(dname, fname_mask,
2848 conn->case_sensitive)) {
2849 TALLOC_FREE(frame);
2850 TALLOC_FREE(talloced);
2851 continue;
2854 TALLOC_FREE(smb_fname->base_name);
2855 if (ISDOT(fname_dir)) {
2856 /* Ensure we use canonical names on open. */
2857 smb_fname->base_name =
2858 talloc_asprintf(smb_fname, "%s",
2859 dname);
2860 } else {
2861 smb_fname->base_name =
2862 talloc_asprintf(smb_fname, "%s/%s",
2863 fname_dir, dname);
2866 if (!smb_fname->base_name) {
2867 TALLOC_FREE(dir_hnd);
2868 status = NT_STATUS_NO_MEMORY;
2869 TALLOC_FREE(frame);
2870 TALLOC_FREE(talloced);
2871 goto out;
2874 status = check_name(conn, smb_fname->base_name);
2875 if (!NT_STATUS_IS_OK(status)) {
2876 TALLOC_FREE(dir_hnd);
2877 TALLOC_FREE(frame);
2878 TALLOC_FREE(talloced);
2879 goto out;
2882 status = do_unlink(conn, req, smb_fname, dirtype);
2883 if (!NT_STATUS_IS_OK(status)) {
2884 TALLOC_FREE(frame);
2885 TALLOC_FREE(talloced);
2886 continue;
2889 count++;
2890 DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2891 smb_fname->base_name));
2893 TALLOC_FREE(frame);
2894 TALLOC_FREE(talloced);
2896 TALLOC_FREE(dir_hnd);
2899 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2900 status = map_nt_error_from_unix(errno);
2903 out:
2904 TALLOC_FREE(fname_dir);
2905 TALLOC_FREE(fname_mask);
2906 return status;
2909 /****************************************************************************
2910 Reply to a unlink
2911 ****************************************************************************/
2913 void reply_unlink(struct smb_request *req)
2915 connection_struct *conn = req->conn;
2916 char *name = NULL;
2917 struct smb_filename *smb_fname = NULL;
2918 uint32 dirtype;
2919 NTSTATUS status;
2920 bool path_contains_wcard = False;
2921 TALLOC_CTX *ctx = talloc_tos();
2923 START_PROFILE(SMBunlink);
2925 if (req->wct < 1) {
2926 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2927 goto out;
2930 dirtype = SVAL(req->vwv+0, 0);
2932 srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2933 STR_TERMINATE, &status,
2934 &path_contains_wcard);
2935 if (!NT_STATUS_IS_OK(status)) {
2936 reply_nterror(req, status);
2937 goto out;
2940 status = filename_convert(ctx, conn,
2941 req->flags2 & FLAGS2_DFS_PATHNAMES,
2942 name,
2943 UCF_COND_ALLOW_WCARD_LCOMP,
2944 &path_contains_wcard,
2945 &smb_fname);
2946 if (!NT_STATUS_IS_OK(status)) {
2947 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2948 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2949 ERRSRV, ERRbadpath);
2950 goto out;
2952 reply_nterror(req, status);
2953 goto out;
2956 DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2958 status = unlink_internals(conn, req, dirtype, smb_fname,
2959 path_contains_wcard);
2960 if (!NT_STATUS_IS_OK(status)) {
2961 if (open_was_deferred(req->sconn, req->mid)) {
2962 /* We have re-scheduled this call. */
2963 goto out;
2965 reply_nterror(req, status);
2966 goto out;
2969 reply_outbuf(req, 0, 0);
2970 out:
2971 TALLOC_FREE(smb_fname);
2972 END_PROFILE(SMBunlink);
2973 return;
2976 /****************************************************************************
2977 Fail for readbraw.
2978 ****************************************************************************/
2980 static void fail_readraw(void)
2982 const char *errstr = talloc_asprintf(talloc_tos(),
2983 "FAIL ! reply_readbraw: socket write fail (%s)",
2984 strerror(errno));
2985 if (!errstr) {
2986 errstr = "";
2988 exit_server_cleanly(errstr);
2991 /****************************************************************************
2992 Fake (read/write) sendfile. Returns -1 on read or write fail.
2993 ****************************************************************************/
2995 ssize_t fake_sendfile(files_struct *fsp, off_t startpos, size_t nread)
2997 size_t bufsize;
2998 size_t tosend = nread;
2999 char *buf;
3001 if (nread == 0) {
3002 return 0;
3005 bufsize = MIN(nread, 65536);
3007 if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
3008 return -1;
3011 while (tosend > 0) {
3012 ssize_t ret;
3013 size_t cur_read;
3015 if (tosend > bufsize) {
3016 cur_read = bufsize;
3017 } else {
3018 cur_read = tosend;
3020 ret = read_file(fsp,buf,startpos,cur_read);
3021 if (ret == -1) {
3022 SAFE_FREE(buf);
3023 return -1;
3026 /* If we had a short read, fill with zeros. */
3027 if (ret < cur_read) {
3028 memset(buf + ret, '\0', cur_read - ret);
3031 if (write_data(fsp->conn->sconn->sock, buf, cur_read)
3032 != cur_read) {
3033 char addr[INET6_ADDRSTRLEN];
3035 * Try and give an error message saying what
3036 * client failed.
3038 DEBUG(0, ("write_data failed for client %s. "
3039 "Error %s\n",
3040 get_peer_addr(fsp->conn->sconn->sock, addr,
3041 sizeof(addr)),
3042 strerror(errno)));
3043 SAFE_FREE(buf);
3044 return -1;
3046 tosend -= cur_read;
3047 startpos += cur_read;
3050 SAFE_FREE(buf);
3051 return (ssize_t)nread;
3054 /****************************************************************************
3055 Deal with the case of sendfile reading less bytes from the file than
3056 requested. Fill with zeros (all we can do).
3057 ****************************************************************************/
3059 void sendfile_short_send(files_struct *fsp,
3060 ssize_t nread,
3061 size_t headersize,
3062 size_t smb_maxcnt)
3064 #define SHORT_SEND_BUFSIZE 1024
3065 if (nread < headersize) {
3066 DEBUG(0,("sendfile_short_send: sendfile failed to send "
3067 "header for file %s (%s). Terminating\n",
3068 fsp_str_dbg(fsp), strerror(errno)));
3069 exit_server_cleanly("sendfile_short_send failed");
3072 nread -= headersize;
3074 if (nread < smb_maxcnt) {
3075 char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
3076 if (!buf) {
3077 exit_server_cleanly("sendfile_short_send: "
3078 "malloc failed");
3081 DEBUG(0,("sendfile_short_send: filling truncated file %s "
3082 "with zeros !\n", fsp_str_dbg(fsp)));
3084 while (nread < smb_maxcnt) {
3086 * We asked for the real file size and told sendfile
3087 * to not go beyond the end of the file. But it can
3088 * happen that in between our fstat call and the
3089 * sendfile call the file was truncated. This is very
3090 * bad because we have already announced the larger
3091 * number of bytes to the client.
3093 * The best we can do now is to send 0-bytes, just as
3094 * a read from a hole in a sparse file would do.
3096 * This should happen rarely enough that I don't care
3097 * about efficiency here :-)
3099 size_t to_write;
3101 to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
3102 if (write_data(fsp->conn->sconn->sock, buf, to_write)
3103 != to_write) {
3104 char addr[INET6_ADDRSTRLEN];
3106 * Try and give an error message saying what
3107 * client failed.
3109 DEBUG(0, ("write_data failed for client %s. "
3110 "Error %s\n",
3111 get_peer_addr(
3112 fsp->conn->sconn->sock, addr,
3113 sizeof(addr)),
3114 strerror(errno)));
3115 exit_server_cleanly("sendfile_short_send: "
3116 "write_data failed");
3118 nread += to_write;
3120 SAFE_FREE(buf);
3124 /****************************************************************************
3125 Return a readbraw error (4 bytes of zero).
3126 ****************************************************************************/
3128 static void reply_readbraw_error(struct smbd_server_connection *sconn)
3130 char header[4];
3132 SIVAL(header,0,0);
3134 smbd_lock_socket(sconn);
3135 if (write_data(sconn->sock,header,4) != 4) {
3136 char addr[INET6_ADDRSTRLEN];
3138 * Try and give an error message saying what
3139 * client failed.
3141 DEBUG(0, ("write_data failed for client %s. "
3142 "Error %s\n",
3143 get_peer_addr(sconn->sock, addr, sizeof(addr)),
3144 strerror(errno)));
3146 fail_readraw();
3148 smbd_unlock_socket(sconn);
3151 /****************************************************************************
3152 Use sendfile in readbraw.
3153 ****************************************************************************/
3155 static void send_file_readbraw(connection_struct *conn,
3156 struct smb_request *req,
3157 files_struct *fsp,
3158 off_t startpos,
3159 size_t nread,
3160 ssize_t mincount)
3162 struct smbd_server_connection *sconn = req->sconn;
3163 char *outbuf = NULL;
3164 ssize_t ret=0;
3167 * We can only use sendfile on a non-chained packet
3168 * but we can use on a non-oplocked file. tridge proved this
3169 * on a train in Germany :-). JRA.
3170 * reply_readbraw has already checked the length.
3173 if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
3174 (fsp->wcp == NULL) &&
3175 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3176 ssize_t sendfile_read = -1;
3177 char header[4];
3178 DATA_BLOB header_blob;
3180 _smb_setlen(header,nread);
3181 header_blob = data_blob_const(header, 4);
3183 sendfile_read = SMB_VFS_SENDFILE(sconn->sock, fsp,
3184 &header_blob, startpos,
3185 nread);
3186 if (sendfile_read == -1) {
3187 /* Returning ENOSYS means no data at all was sent.
3188 * Do this as a normal read. */
3189 if (errno == ENOSYS) {
3190 goto normal_readbraw;
3194 * Special hack for broken Linux with no working sendfile. If we
3195 * return EINTR we sent the header but not the rest of the data.
3196 * Fake this up by doing read/write calls.
3198 if (errno == EINTR) {
3199 /* Ensure we don't do this again. */
3200 set_use_sendfile(SNUM(conn), False);
3201 DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
3203 if (fake_sendfile(fsp, startpos, nread) == -1) {
3204 DEBUG(0,("send_file_readbraw: "
3205 "fake_sendfile failed for "
3206 "file %s (%s).\n",
3207 fsp_str_dbg(fsp),
3208 strerror(errno)));
3209 exit_server_cleanly("send_file_readbraw fake_sendfile failed");
3211 return;
3214 DEBUG(0,("send_file_readbraw: sendfile failed for "
3215 "file %s (%s). Terminating\n",
3216 fsp_str_dbg(fsp), strerror(errno)));
3217 exit_server_cleanly("send_file_readbraw sendfile failed");
3218 } else if (sendfile_read == 0) {
3220 * Some sendfile implementations return 0 to indicate
3221 * that there was a short read, but nothing was
3222 * actually written to the socket. In this case,
3223 * fallback to the normal read path so the header gets
3224 * the correct byte count.
3226 DEBUG(3, ("send_file_readbraw: sendfile sent zero "
3227 "bytes falling back to the normal read: "
3228 "%s\n", fsp_str_dbg(fsp)));
3229 goto normal_readbraw;
3232 /* Deal with possible short send. */
3233 if (sendfile_read != 4+nread) {
3234 sendfile_short_send(fsp, sendfile_read, 4, nread);
3236 return;
3239 normal_readbraw:
3241 outbuf = talloc_array(NULL, char, nread+4);
3242 if (!outbuf) {
3243 DEBUG(0,("send_file_readbraw: talloc_array failed for size %u.\n",
3244 (unsigned)(nread+4)));
3245 reply_readbraw_error(sconn);
3246 return;
3249 if (nread > 0) {
3250 ret = read_file(fsp,outbuf+4,startpos,nread);
3251 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3252 if (ret < mincount)
3253 ret = 0;
3254 #else
3255 if (ret < nread)
3256 ret = 0;
3257 #endif
3260 _smb_setlen(outbuf,ret);
3261 if (write_data(sconn->sock, outbuf, 4+ret) != 4+ret) {
3262 char addr[INET6_ADDRSTRLEN];
3264 * Try and give an error message saying what
3265 * client failed.
3267 DEBUG(0, ("write_data failed for client %s. "
3268 "Error %s\n",
3269 get_peer_addr(fsp->conn->sconn->sock, addr,
3270 sizeof(addr)),
3271 strerror(errno)));
3273 fail_readraw();
3276 TALLOC_FREE(outbuf);
3279 /****************************************************************************
3280 Reply to a readbraw (core+ protocol).
3281 ****************************************************************************/
3283 void reply_readbraw(struct smb_request *req)
3285 connection_struct *conn = req->conn;
3286 struct smbd_server_connection *sconn = req->sconn;
3287 ssize_t maxcount,mincount;
3288 size_t nread = 0;
3289 off_t startpos;
3290 files_struct *fsp;
3291 struct lock_struct lock;
3292 off_t size = 0;
3294 START_PROFILE(SMBreadbraw);
3296 if (srv_is_signing_active(sconn) ||
3297 is_encrypted_packet(sconn, req->inbuf)) {
3298 exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3299 "raw reads/writes are disallowed.");
3302 if (req->wct < 8) {
3303 reply_readbraw_error(sconn);
3304 END_PROFILE(SMBreadbraw);
3305 return;
3308 if (sconn->smb1.echo_handler.trusted_fde) {
3309 DEBUG(2,("SMBreadbraw rejected with NOT_SUPPORTED because of "
3310 "'async smb echo handler = yes'\n"));
3311 reply_readbraw_error(sconn);
3312 END_PROFILE(SMBreadbraw);
3313 return;
3317 * Special check if an oplock break has been issued
3318 * and the readraw request croses on the wire, we must
3319 * return a zero length response here.
3322 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3325 * We have to do a check_fsp by hand here, as
3326 * we must always return 4 zero bytes on error,
3327 * not a NTSTATUS.
3330 if (!fsp || !conn || conn != fsp->conn ||
3331 req->vuid != fsp->vuid ||
3332 fsp->is_directory || fsp->fh->fd == -1) {
3334 * fsp could be NULL here so use the value from the packet. JRA.
3336 DEBUG(3,("reply_readbraw: fnum %d not valid "
3337 "- cache prime?\n",
3338 (int)SVAL(req->vwv+0, 0)));
3339 reply_readbraw_error(sconn);
3340 END_PROFILE(SMBreadbraw);
3341 return;
3344 /* Do a "by hand" version of CHECK_READ. */
3345 if (!(fsp->can_read ||
3346 ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3347 (fsp->access_mask & FILE_EXECUTE)))) {
3348 DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3349 (int)SVAL(req->vwv+0, 0)));
3350 reply_readbraw_error(sconn);
3351 END_PROFILE(SMBreadbraw);
3352 return;
3355 flush_write_cache(fsp, READRAW_FLUSH);
3357 startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3358 if(req->wct == 10) {
3360 * This is a large offset (64 bit) read.
3363 startpos |= (((off_t)IVAL(req->vwv+8, 0)) << 32);
3365 if(startpos < 0) {
3366 DEBUG(0,("reply_readbraw: negative 64 bit "
3367 "readraw offset (%.0f) !\n",
3368 (double)startpos ));
3369 reply_readbraw_error(sconn);
3370 END_PROFILE(SMBreadbraw);
3371 return;
3375 maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3376 mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3378 /* ensure we don't overrun the packet size */
3379 maxcount = MIN(65535,maxcount);
3381 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3382 (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3383 &lock);
3385 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3386 reply_readbraw_error(sconn);
3387 END_PROFILE(SMBreadbraw);
3388 return;
3391 if (fsp_stat(fsp) == 0) {
3392 size = fsp->fsp_name->st.st_ex_size;
3395 if (startpos >= size) {
3396 nread = 0;
3397 } else {
3398 nread = MIN(maxcount,(size - startpos));
3401 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3402 if (nread < mincount)
3403 nread = 0;
3404 #endif
3406 DEBUG( 3, ( "reply_readbraw: %s start=%.0f max=%lu "
3407 "min=%lu nread=%lu\n",
3408 fsp_fnum_dbg(fsp), (double)startpos,
3409 (unsigned long)maxcount,
3410 (unsigned long)mincount,
3411 (unsigned long)nread ) );
3413 send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3415 DEBUG(5,("reply_readbraw finished\n"));
3417 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3419 END_PROFILE(SMBreadbraw);
3420 return;
3423 #undef DBGC_CLASS
3424 #define DBGC_CLASS DBGC_LOCKING
3426 /****************************************************************************
3427 Reply to a lockread (core+ protocol).
3428 ****************************************************************************/
3430 void reply_lockread(struct smb_request *req)
3432 connection_struct *conn = req->conn;
3433 ssize_t nread = -1;
3434 char *data;
3435 off_t startpos;
3436 size_t numtoread;
3437 NTSTATUS status;
3438 files_struct *fsp;
3439 struct byte_range_lock *br_lck = NULL;
3440 char *p = NULL;
3441 struct smbd_server_connection *sconn = req->sconn;
3443 START_PROFILE(SMBlockread);
3445 if (req->wct < 5) {
3446 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3447 END_PROFILE(SMBlockread);
3448 return;
3451 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3453 if (!check_fsp(conn, req, fsp)) {
3454 END_PROFILE(SMBlockread);
3455 return;
3458 if (!CHECK_READ(fsp,req)) {
3459 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3460 END_PROFILE(SMBlockread);
3461 return;
3464 numtoread = SVAL(req->vwv+1, 0);
3465 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3467 numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3469 reply_outbuf(req, 5, numtoread + 3);
3471 data = smb_buf(req->outbuf) + 3;
3474 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3475 * protocol request that predates the read/write lock concept.
3476 * Thus instead of asking for a read lock here we need to ask
3477 * for a write lock. JRA.
3478 * Note that the requested lock size is unaffected by max_recv.
3481 br_lck = do_lock(req->sconn->msg_ctx,
3482 fsp,
3483 (uint64_t)req->smbpid,
3484 (uint64_t)numtoread,
3485 (uint64_t)startpos,
3486 WRITE_LOCK,
3487 WINDOWS_LOCK,
3488 False, /* Non-blocking lock. */
3489 &status,
3490 NULL,
3491 NULL);
3492 TALLOC_FREE(br_lck);
3494 if (NT_STATUS_V(status)) {
3495 reply_nterror(req, status);
3496 END_PROFILE(SMBlockread);
3497 return;
3501 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3504 if (numtoread > sconn->smb1.negprot.max_recv) {
3505 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3506 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3507 (unsigned int)numtoread,
3508 (unsigned int)sconn->smb1.negprot.max_recv));
3509 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3511 nread = read_file(fsp,data,startpos,numtoread);
3513 if (nread < 0) {
3514 reply_nterror(req, map_nt_error_from_unix(errno));
3515 END_PROFILE(SMBlockread);
3516 return;
3519 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3521 SSVAL(req->outbuf,smb_vwv0,nread);
3522 SSVAL(req->outbuf,smb_vwv5,nread+3);
3523 p = smb_buf(req->outbuf);
3524 SCVAL(p,0,0); /* pad byte. */
3525 SSVAL(p,1,nread);
3527 DEBUG(3,("lockread %s num=%d nread=%d\n",
3528 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3530 END_PROFILE(SMBlockread);
3531 return;
3534 #undef DBGC_CLASS
3535 #define DBGC_CLASS DBGC_ALL
3537 /****************************************************************************
3538 Reply to a read.
3539 ****************************************************************************/
3541 void reply_read(struct smb_request *req)
3543 connection_struct *conn = req->conn;
3544 size_t numtoread;
3545 ssize_t nread = 0;
3546 char *data;
3547 off_t startpos;
3548 int outsize = 0;
3549 files_struct *fsp;
3550 struct lock_struct lock;
3551 struct smbd_server_connection *sconn = req->sconn;
3553 START_PROFILE(SMBread);
3555 if (req->wct < 3) {
3556 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3557 END_PROFILE(SMBread);
3558 return;
3561 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3563 if (!check_fsp(conn, req, fsp)) {
3564 END_PROFILE(SMBread);
3565 return;
3568 if (!CHECK_READ(fsp,req)) {
3569 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3570 END_PROFILE(SMBread);
3571 return;
3574 numtoread = SVAL(req->vwv+1, 0);
3575 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3577 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3580 * The requested read size cannot be greater than max_recv. JRA.
3582 if (numtoread > sconn->smb1.negprot.max_recv) {
3583 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3584 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3585 (unsigned int)numtoread,
3586 (unsigned int)sconn->smb1.negprot.max_recv));
3587 numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3590 reply_outbuf(req, 5, numtoread+3);
3592 data = smb_buf(req->outbuf) + 3;
3594 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3595 (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3596 &lock);
3598 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3599 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3600 END_PROFILE(SMBread);
3601 return;
3604 if (numtoread > 0)
3605 nread = read_file(fsp,data,startpos,numtoread);
3607 if (nread < 0) {
3608 reply_nterror(req, map_nt_error_from_unix(errno));
3609 goto strict_unlock;
3612 srv_set_message((char *)req->outbuf, 5, nread+3, False);
3614 SSVAL(req->outbuf,smb_vwv0,nread);
3615 SSVAL(req->outbuf,smb_vwv5,nread+3);
3616 SCVAL(smb_buf(req->outbuf),0,1);
3617 SSVAL(smb_buf(req->outbuf),1,nread);
3619 DEBUG(3, ("read %s num=%d nread=%d\n",
3620 fsp_fnum_dbg(fsp), (int)numtoread, (int)nread));
3622 strict_unlock:
3623 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3625 END_PROFILE(SMBread);
3626 return;
3629 /****************************************************************************
3630 Setup readX header.
3631 ****************************************************************************/
3633 static int setup_readX_header(struct smb_request *req, char *outbuf,
3634 size_t smb_maxcnt)
3636 int outsize;
3638 outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3640 memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3642 SCVAL(outbuf,smb_vwv0,0xFF);
3643 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3644 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3645 SSVAL(outbuf,smb_vwv6,
3646 (smb_wct - 4) /* offset from smb header to wct */
3647 + 1 /* the wct field */
3648 + 12 * sizeof(uint16_t) /* vwv */
3649 + 2); /* the buflen field */
3650 SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3651 SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3652 /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3653 _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3654 return outsize;
3657 /****************************************************************************
3658 Reply to a read and X - possibly using sendfile.
3659 ****************************************************************************/
3661 static void send_file_readX(connection_struct *conn, struct smb_request *req,
3662 files_struct *fsp, off_t startpos,
3663 size_t smb_maxcnt)
3665 ssize_t nread = -1;
3666 struct lock_struct lock;
3667 int saved_errno = 0;
3669 if(fsp_stat(fsp) == -1) {
3670 reply_nterror(req, map_nt_error_from_unix(errno));
3671 return;
3674 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
3675 (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3676 &lock);
3678 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3679 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3680 return;
3683 if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3684 (startpos > fsp->fsp_name->st.st_ex_size)
3685 || (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3687 * We already know that we would do a short read, so don't
3688 * try the sendfile() path.
3690 goto nosendfile_read;
3694 * We can only use sendfile on a non-chained packet
3695 * but we can use on a non-oplocked file. tridge proved this
3696 * on a train in Germany :-). JRA.
3699 if (!req_is_in_chain(req) &&
3700 !is_encrypted_packet(req->sconn, req->inbuf) &&
3701 (fsp->base_fsp == NULL) &&
3702 (fsp->wcp == NULL) &&
3703 lp_use_sendfile(SNUM(conn), req->sconn->smb1.signing_state) ) {
3704 uint8 headerbuf[smb_size + 12 * 2];
3705 DATA_BLOB header;
3708 * Set up the packet header before send. We
3709 * assume here the sendfile will work (get the
3710 * correct amount of data).
3713 header = data_blob_const(headerbuf, sizeof(headerbuf));
3715 construct_reply_common_req(req, (char *)headerbuf);
3716 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3718 nread = SMB_VFS_SENDFILE(req->sconn->sock, fsp, &header,
3719 startpos, smb_maxcnt);
3720 if (nread == -1) {
3721 /* Returning ENOSYS means no data at all was sent.
3722 Do this as a normal read. */
3723 if (errno == ENOSYS) {
3724 goto normal_read;
3728 * Special hack for broken Linux with no working sendfile. If we
3729 * return EINTR we sent the header but not the rest of the data.
3730 * Fake this up by doing read/write calls.
3733 if (errno == EINTR) {
3734 /* Ensure we don't do this again. */
3735 set_use_sendfile(SNUM(conn), False);
3736 DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3737 nread = fake_sendfile(fsp, startpos,
3738 smb_maxcnt);
3739 if (nread == -1) {
3740 DEBUG(0,("send_file_readX: "
3741 "fake_sendfile failed for "
3742 "file %s (%s).\n",
3743 fsp_str_dbg(fsp),
3744 strerror(errno)));
3745 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3747 DEBUG(3, ("send_file_readX: fake_sendfile %s max=%d nread=%d\n",
3748 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3749 /* No outbuf here means successful sendfile. */
3750 goto strict_unlock;
3753 DEBUG(0,("send_file_readX: sendfile failed for file "
3754 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3755 strerror(errno)));
3756 exit_server_cleanly("send_file_readX sendfile failed");
3757 } else if (nread == 0) {
3759 * Some sendfile implementations return 0 to indicate
3760 * that there was a short read, but nothing was
3761 * actually written to the socket. In this case,
3762 * fallback to the normal read path so the header gets
3763 * the correct byte count.
3765 DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3766 "falling back to the normal read: %s\n",
3767 fsp_str_dbg(fsp)));
3768 goto normal_read;
3771 DEBUG(3, ("send_file_readX: sendfile %s max=%d nread=%d\n",
3772 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3774 /* Deal with possible short send. */
3775 if (nread != smb_maxcnt + sizeof(headerbuf)) {
3776 sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3778 /* No outbuf here means successful sendfile. */
3779 SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3780 SMB_PERFCOUNT_END(&req->pcd);
3781 goto strict_unlock;
3784 normal_read:
3786 if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3787 uint8 headerbuf[smb_size + 2*12];
3789 construct_reply_common_req(req, (char *)headerbuf);
3790 setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3792 /* Send out the header. */
3793 if (write_data(req->sconn->sock, (char *)headerbuf,
3794 sizeof(headerbuf)) != sizeof(headerbuf)) {
3796 char addr[INET6_ADDRSTRLEN];
3798 * Try and give an error message saying what
3799 * client failed.
3801 DEBUG(0, ("write_data failed for client %s. "
3802 "Error %s\n",
3803 get_peer_addr(req->sconn->sock, addr,
3804 sizeof(addr)),
3805 strerror(errno)));
3807 DEBUG(0,("send_file_readX: write_data failed for file "
3808 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3809 strerror(errno)));
3810 exit_server_cleanly("send_file_readX sendfile failed");
3812 nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3813 if (nread == -1) {
3814 DEBUG(0,("send_file_readX: fake_sendfile failed for "
3815 "file %s (%s).\n", fsp_str_dbg(fsp),
3816 strerror(errno)));
3817 exit_server_cleanly("send_file_readX: fake_sendfile failed");
3819 goto strict_unlock;
3822 nosendfile_read:
3824 reply_outbuf(req, 12, smb_maxcnt);
3825 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
3826 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
3828 nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3829 saved_errno = errno;
3831 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3833 if (nread < 0) {
3834 reply_nterror(req, map_nt_error_from_unix(saved_errno));
3835 return;
3838 setup_readX_header(req, (char *)req->outbuf, nread);
3840 DEBUG(3, ("send_file_readX %s max=%d nread=%d\n",
3841 fsp_fnum_dbg(fsp), (int)smb_maxcnt, (int)nread));
3842 return;
3844 strict_unlock:
3845 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3846 TALLOC_FREE(req->outbuf);
3847 return;
3850 /****************************************************************************
3851 Reply to a read and X.
3852 ****************************************************************************/
3854 void reply_read_and_X(struct smb_request *req)
3856 struct smbd_server_connection *sconn = req->sconn;
3857 connection_struct *conn = req->conn;
3858 files_struct *fsp;
3859 off_t startpos;
3860 size_t smb_maxcnt;
3861 bool big_readX = False;
3862 #if 0
3863 size_t smb_mincnt = SVAL(req->vwv+6, 0);
3864 #endif
3866 START_PROFILE(SMBreadX);
3868 if ((req->wct != 10) && (req->wct != 12)) {
3869 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3870 return;
3873 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3874 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3875 smb_maxcnt = SVAL(req->vwv+5, 0);
3877 /* If it's an IPC, pass off the pipe handler. */
3878 if (IS_IPC(conn)) {
3879 reply_pipe_read_and_X(req);
3880 END_PROFILE(SMBreadX);
3881 return;
3884 if (!check_fsp(conn, req, fsp)) {
3885 END_PROFILE(SMBreadX);
3886 return;
3889 if (!CHECK_READ(fsp,req)) {
3890 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3891 END_PROFILE(SMBreadX);
3892 return;
3895 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_LARGE_READ_CAP) ||
3896 (get_remote_arch() == RA_SAMBA)) {
3898 * This is Samba only behavior (up to Samba 3.6)!
3900 * Windows 2008 R2 ignores the upper_size,
3901 * so we do unless unix extentions are active
3902 * or "smbclient" is talking to us.
3904 size_t upper_size = SVAL(req->vwv+7, 0);
3905 smb_maxcnt |= (upper_size<<16);
3906 if (upper_size > 1) {
3907 /* Can't do this on a chained packet. */
3908 if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3909 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3910 END_PROFILE(SMBreadX);
3911 return;
3913 /* We currently don't do this on signed or sealed data. */
3914 if (srv_is_signing_active(req->sconn) ||
3915 is_encrypted_packet(req->sconn, req->inbuf)) {
3916 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3917 END_PROFILE(SMBreadX);
3918 return;
3920 /* Is there room in the reply for this data ? */
3921 if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
3922 reply_nterror(req,
3923 NT_STATUS_INVALID_PARAMETER);
3924 END_PROFILE(SMBreadX);
3925 return;
3927 big_readX = True;
3931 if (req->wct == 12) {
3933 * This is a large offset (64 bit) read.
3935 startpos |= (((off_t)IVAL(req->vwv+10, 0)) << 32);
3939 if (!big_readX) {
3940 NTSTATUS status = schedule_aio_read_and_X(conn,
3941 req,
3942 fsp,
3943 startpos,
3944 smb_maxcnt);
3945 if (NT_STATUS_IS_OK(status)) {
3946 /* Read scheduled - we're done. */
3947 goto out;
3949 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
3950 /* Real error - report to client. */
3951 END_PROFILE(SMBreadX);
3952 reply_nterror(req, status);
3953 return;
3955 /* NT_STATUS_RETRY - fall back to sync read. */
3958 smbd_lock_socket(req->sconn);
3959 send_file_readX(conn, req, fsp, startpos, smb_maxcnt);
3960 smbd_unlock_socket(req->sconn);
3962 out:
3963 END_PROFILE(SMBreadX);
3964 return;
3967 /****************************************************************************
3968 Error replies to writebraw must have smb_wct == 1. Fix this up.
3969 ****************************************************************************/
3971 void error_to_writebrawerr(struct smb_request *req)
3973 uint8 *old_outbuf = req->outbuf;
3975 reply_outbuf(req, 1, 0);
3977 memcpy(req->outbuf, old_outbuf, smb_size);
3978 TALLOC_FREE(old_outbuf);
3981 /****************************************************************************
3982 Read 4 bytes of a smb packet and return the smb length of the packet.
3983 Store the result in the buffer. This version of the function will
3984 never return a session keepalive (length of zero).
3985 Timeout is in milliseconds.
3986 ****************************************************************************/
3988 static NTSTATUS read_smb_length(int fd, char *inbuf, unsigned int timeout,
3989 size_t *len)
3991 uint8_t msgtype = NBSSkeepalive;
3993 while (msgtype == NBSSkeepalive) {
3994 NTSTATUS status;
3996 status = read_smb_length_return_keepalive(fd, inbuf, timeout,
3997 len);
3998 if (!NT_STATUS_IS_OK(status)) {
3999 char addr[INET6_ADDRSTRLEN];
4000 /* Try and give an error message
4001 * saying what client failed. */
4002 DEBUG(0, ("read_fd_with_timeout failed for "
4003 "client %s read error = %s.\n",
4004 get_peer_addr(fd,addr,sizeof(addr)),
4005 nt_errstr(status)));
4006 return status;
4009 msgtype = CVAL(inbuf, 0);
4012 DEBUG(10,("read_smb_length: got smb length of %lu\n",
4013 (unsigned long)len));
4015 return NT_STATUS_OK;
4018 /****************************************************************************
4019 Reply to a writebraw (core+ or LANMAN1.0 protocol).
4020 ****************************************************************************/
4022 void reply_writebraw(struct smb_request *req)
4024 connection_struct *conn = req->conn;
4025 char *buf = NULL;
4026 ssize_t nwritten=0;
4027 ssize_t total_written=0;
4028 size_t numtowrite=0;
4029 size_t tcount;
4030 off_t startpos;
4031 const char *data=NULL;
4032 bool write_through;
4033 files_struct *fsp;
4034 struct lock_struct lock;
4035 NTSTATUS status;
4037 START_PROFILE(SMBwritebraw);
4040 * If we ever reply with an error, it must have the SMB command
4041 * type of SMBwritec, not SMBwriteBraw, as this tells the client
4042 * we're finished.
4044 SCVAL(discard_const_p(uint8_t, req->inbuf),smb_com,SMBwritec);
4046 if (srv_is_signing_active(req->sconn)) {
4047 END_PROFILE(SMBwritebraw);
4048 exit_server_cleanly("reply_writebraw: SMB signing is active - "
4049 "raw reads/writes are disallowed.");
4052 if (req->wct < 12) {
4053 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4054 error_to_writebrawerr(req);
4055 END_PROFILE(SMBwritebraw);
4056 return;
4059 if (req->sconn->smb1.echo_handler.trusted_fde) {
4060 DEBUG(2,("SMBwritebraw rejected with NOT_SUPPORTED because of "
4061 "'async smb echo handler = yes'\n"));
4062 reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
4063 error_to_writebrawerr(req);
4064 END_PROFILE(SMBwritebraw);
4065 return;
4068 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4069 if (!check_fsp(conn, req, fsp)) {
4070 error_to_writebrawerr(req);
4071 END_PROFILE(SMBwritebraw);
4072 return;
4075 if (!CHECK_WRITE(fsp)) {
4076 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4077 error_to_writebrawerr(req);
4078 END_PROFILE(SMBwritebraw);
4079 return;
4082 tcount = IVAL(req->vwv+1, 0);
4083 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4084 write_through = BITSETW(req->vwv+7,0);
4086 /* We have to deal with slightly different formats depending
4087 on whether we are using the core+ or lanman1.0 protocol */
4089 if(get_Protocol() <= PROTOCOL_COREPLUS) {
4090 numtowrite = SVAL(smb_buf_const(req->inbuf),-2);
4091 data = smb_buf_const(req->inbuf);
4092 } else {
4093 numtowrite = SVAL(req->vwv+10, 0);
4094 data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
4097 /* Ensure we don't write bytes past the end of this packet. */
4098 if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
4099 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4100 error_to_writebrawerr(req);
4101 END_PROFILE(SMBwritebraw);
4102 return;
4105 if (!fsp->print_file) {
4106 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4107 (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
4108 &lock);
4110 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4111 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4112 error_to_writebrawerr(req);
4113 END_PROFILE(SMBwritebraw);
4114 return;
4118 if (numtowrite>0) {
4119 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4122 DEBUG(3, ("reply_writebraw: initial write %s start=%.0f num=%d "
4123 "wrote=%d sync=%d\n",
4124 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4125 (int)nwritten, (int)write_through));
4127 if (nwritten < (ssize_t)numtowrite) {
4128 reply_nterror(req, NT_STATUS_DISK_FULL);
4129 error_to_writebrawerr(req);
4130 goto strict_unlock;
4133 total_written = nwritten;
4135 /* Allocate a buffer of 64k + length. */
4136 buf = talloc_array(NULL, char, 65540);
4137 if (!buf) {
4138 reply_nterror(req, NT_STATUS_NO_MEMORY);
4139 error_to_writebrawerr(req);
4140 goto strict_unlock;
4143 /* Return a SMBwritebraw message to the redirector to tell
4144 * it to send more bytes */
4146 memcpy(buf, req->inbuf, smb_size);
4147 srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
4148 SCVAL(buf,smb_com,SMBwritebraw);
4149 SSVALS(buf,smb_vwv0,0xFFFF);
4150 show_msg(buf);
4151 if (!srv_send_smb(req->sconn,
4152 buf,
4153 false, 0, /* no signing */
4154 IS_CONN_ENCRYPTED(conn),
4155 &req->pcd)) {
4156 exit_server_cleanly("reply_writebraw: srv_send_smb "
4157 "failed.");
4160 /* Now read the raw data into the buffer and write it */
4161 status = read_smb_length(req->sconn->sock, buf, SMB_SECONDARY_WAIT,
4162 &numtowrite);
4163 if (!NT_STATUS_IS_OK(status)) {
4164 exit_server_cleanly("secondary writebraw failed");
4167 /* Set up outbuf to return the correct size */
4168 reply_outbuf(req, 1, 0);
4170 if (numtowrite != 0) {
4172 if (numtowrite > 0xFFFF) {
4173 DEBUG(0,("reply_writebraw: Oversize secondary write "
4174 "raw requested (%u). Terminating\n",
4175 (unsigned int)numtowrite ));
4176 exit_server_cleanly("secondary writebraw failed");
4179 if (tcount > nwritten+numtowrite) {
4180 DEBUG(3,("reply_writebraw: Client overestimated the "
4181 "write %d %d %d\n",
4182 (int)tcount,(int)nwritten,(int)numtowrite));
4185 status = read_data(req->sconn->sock, buf+4, numtowrite);
4187 if (!NT_STATUS_IS_OK(status)) {
4188 char addr[INET6_ADDRSTRLEN];
4189 /* Try and give an error message
4190 * saying what client failed. */
4191 DEBUG(0, ("reply_writebraw: Oversize secondary write "
4192 "raw read failed (%s) for client %s. "
4193 "Terminating\n", nt_errstr(status),
4194 get_peer_addr(req->sconn->sock, addr,
4195 sizeof(addr))));
4196 exit_server_cleanly("secondary writebraw failed");
4199 nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
4200 if (nwritten == -1) {
4201 TALLOC_FREE(buf);
4202 reply_nterror(req, map_nt_error_from_unix(errno));
4203 error_to_writebrawerr(req);
4204 goto strict_unlock;
4207 if (nwritten < (ssize_t)numtowrite) {
4208 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4209 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4212 if (nwritten > 0) {
4213 total_written += nwritten;
4217 TALLOC_FREE(buf);
4218 SSVAL(req->outbuf,smb_vwv0,total_written);
4220 status = sync_file(conn, fsp, write_through);
4221 if (!NT_STATUS_IS_OK(status)) {
4222 DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
4223 fsp_str_dbg(fsp), nt_errstr(status)));
4224 reply_nterror(req, status);
4225 error_to_writebrawerr(req);
4226 goto strict_unlock;
4229 DEBUG(3,("reply_writebraw: secondart write %s start=%.0f num=%d "
4230 "wrote=%d\n",
4231 fsp_fnum_dbg(fsp), (double)startpos, (int)numtowrite,
4232 (int)total_written));
4234 if (!fsp->print_file) {
4235 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4238 /* We won't return a status if write through is not selected - this
4239 * follows what WfWg does */
4240 END_PROFILE(SMBwritebraw);
4242 if (!write_through && total_written==tcount) {
4244 #if RABBIT_PELLET_FIX
4246 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
4247 * sending a NBSSkeepalive. Thanks to DaveCB at Sun for this.
4248 * JRA.
4250 if (!send_keepalive(req->sconn->sock)) {
4251 exit_server_cleanly("reply_writebraw: send of "
4252 "keepalive failed");
4254 #endif
4255 TALLOC_FREE(req->outbuf);
4257 return;
4259 strict_unlock:
4260 if (!fsp->print_file) {
4261 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4264 END_PROFILE(SMBwritebraw);
4265 return;
4268 #undef DBGC_CLASS
4269 #define DBGC_CLASS DBGC_LOCKING
4271 /****************************************************************************
4272 Reply to a writeunlock (core+).
4273 ****************************************************************************/
4275 void reply_writeunlock(struct smb_request *req)
4277 connection_struct *conn = req->conn;
4278 ssize_t nwritten = -1;
4279 size_t numtowrite;
4280 off_t startpos;
4281 const char *data;
4282 NTSTATUS status = NT_STATUS_OK;
4283 files_struct *fsp;
4284 struct lock_struct lock;
4285 int saved_errno = 0;
4287 START_PROFILE(SMBwriteunlock);
4289 if (req->wct < 5) {
4290 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4291 END_PROFILE(SMBwriteunlock);
4292 return;
4295 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4297 if (!check_fsp(conn, req, fsp)) {
4298 END_PROFILE(SMBwriteunlock);
4299 return;
4302 if (!CHECK_WRITE(fsp)) {
4303 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4304 END_PROFILE(SMBwriteunlock);
4305 return;
4308 numtowrite = SVAL(req->vwv+1, 0);
4309 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4310 data = (const char *)req->buf + 3;
4312 if (!fsp->print_file && numtowrite > 0) {
4313 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4314 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4315 &lock);
4317 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4318 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4319 END_PROFILE(SMBwriteunlock);
4320 return;
4324 /* The special X/Open SMB protocol handling of
4325 zero length writes is *NOT* done for
4326 this call */
4327 if(numtowrite == 0) {
4328 nwritten = 0;
4329 } else {
4330 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4331 saved_errno = errno;
4334 status = sync_file(conn, fsp, False /* write through */);
4335 if (!NT_STATUS_IS_OK(status)) {
4336 DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4337 fsp_str_dbg(fsp), nt_errstr(status)));
4338 reply_nterror(req, status);
4339 goto strict_unlock;
4342 if(nwritten < 0) {
4343 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4344 goto strict_unlock;
4347 if((nwritten < numtowrite) && (numtowrite != 0)) {
4348 reply_nterror(req, NT_STATUS_DISK_FULL);
4349 goto strict_unlock;
4352 if (numtowrite && !fsp->print_file) {
4353 status = do_unlock(req->sconn->msg_ctx,
4354 fsp,
4355 (uint64_t)req->smbpid,
4356 (uint64_t)numtowrite,
4357 (uint64_t)startpos,
4358 WINDOWS_LOCK);
4360 if (NT_STATUS_V(status)) {
4361 reply_nterror(req, status);
4362 goto strict_unlock;
4366 reply_outbuf(req, 1, 0);
4368 SSVAL(req->outbuf,smb_vwv0,nwritten);
4370 DEBUG(3, ("writeunlock %s num=%d wrote=%d\n",
4371 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4373 strict_unlock:
4374 if (numtowrite && !fsp->print_file) {
4375 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4378 END_PROFILE(SMBwriteunlock);
4379 return;
4382 #undef DBGC_CLASS
4383 #define DBGC_CLASS DBGC_ALL
4385 /****************************************************************************
4386 Reply to a write.
4387 ****************************************************************************/
4389 void reply_write(struct smb_request *req)
4391 connection_struct *conn = req->conn;
4392 size_t numtowrite;
4393 ssize_t nwritten = -1;
4394 off_t startpos;
4395 const char *data;
4396 files_struct *fsp;
4397 struct lock_struct lock;
4398 NTSTATUS status;
4399 int saved_errno = 0;
4401 START_PROFILE(SMBwrite);
4403 if (req->wct < 5) {
4404 END_PROFILE(SMBwrite);
4405 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4406 return;
4409 /* If it's an IPC, pass off the pipe handler. */
4410 if (IS_IPC(conn)) {
4411 reply_pipe_write(req);
4412 END_PROFILE(SMBwrite);
4413 return;
4416 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4418 if (!check_fsp(conn, req, fsp)) {
4419 END_PROFILE(SMBwrite);
4420 return;
4423 if (!CHECK_WRITE(fsp)) {
4424 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4425 END_PROFILE(SMBwrite);
4426 return;
4429 numtowrite = SVAL(req->vwv+1, 0);
4430 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4431 data = (const char *)req->buf + 3;
4433 if (!fsp->print_file) {
4434 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4435 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4436 &lock);
4438 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4439 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4440 END_PROFILE(SMBwrite);
4441 return;
4446 * X/Open SMB protocol says that if smb_vwv1 is
4447 * zero then the file size should be extended or
4448 * truncated to the size given in smb_vwv[2-3].
4451 if(numtowrite == 0) {
4453 * This is actually an allocate call, and set EOF. JRA.
4455 nwritten = vfs_allocate_file_space(fsp, (off_t)startpos);
4456 if (nwritten < 0) {
4457 reply_nterror(req, NT_STATUS_DISK_FULL);
4458 goto strict_unlock;
4460 nwritten = vfs_set_filelen(fsp, (off_t)startpos);
4461 if (nwritten < 0) {
4462 reply_nterror(req, NT_STATUS_DISK_FULL);
4463 goto strict_unlock;
4465 trigger_write_time_update_immediate(fsp);
4466 } else {
4467 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4470 status = sync_file(conn, fsp, False);
4471 if (!NT_STATUS_IS_OK(status)) {
4472 DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4473 fsp_str_dbg(fsp), nt_errstr(status)));
4474 reply_nterror(req, status);
4475 goto strict_unlock;
4478 if(nwritten < 0) {
4479 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4480 goto strict_unlock;
4483 if((nwritten == 0) && (numtowrite != 0)) {
4484 reply_nterror(req, NT_STATUS_DISK_FULL);
4485 goto strict_unlock;
4488 reply_outbuf(req, 1, 0);
4490 SSVAL(req->outbuf,smb_vwv0,nwritten);
4492 if (nwritten < (ssize_t)numtowrite) {
4493 SCVAL(req->outbuf,smb_rcls,ERRHRD);
4494 SSVAL(req->outbuf,smb_err,ERRdiskfull);
4497 DEBUG(3, ("write %s num=%d wrote=%d\n", fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4499 strict_unlock:
4500 if (!fsp->print_file) {
4501 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4504 END_PROFILE(SMBwrite);
4505 return;
4508 /****************************************************************************
4509 Ensure a buffer is a valid writeX for recvfile purposes.
4510 ****************************************************************************/
4512 #define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4513 (2*14) + /* word count (including bcc) */ \
4514 1 /* pad byte */)
4516 bool is_valid_writeX_buffer(struct smbd_server_connection *sconn,
4517 const uint8_t *inbuf)
4519 size_t numtowrite;
4520 connection_struct *conn = NULL;
4521 unsigned int doff = 0;
4522 size_t len = smb_len_large(inbuf);
4523 struct smbXsrv_tcon *tcon;
4524 NTSTATUS status;
4525 NTTIME now = 0;
4527 if (is_encrypted_packet(sconn, inbuf)) {
4528 /* Can't do this on encrypted
4529 * connections. */
4530 return false;
4533 if (CVAL(inbuf,smb_com) != SMBwriteX) {
4534 return false;
4537 if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4538 CVAL(inbuf,smb_wct) != 14) {
4539 DEBUG(10,("is_valid_writeX_buffer: chained or "
4540 "invalid word length.\n"));
4541 return false;
4544 status = smb1srv_tcon_lookup(sconn->conn, SVAL(inbuf, smb_tid),
4545 now, &tcon);
4546 if (!NT_STATUS_IS_OK(status)) {
4547 DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4548 return false;
4550 conn = tcon->compat;
4552 if (IS_IPC(conn)) {
4553 DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4554 return false;
4556 if (IS_PRINT(conn)) {
4557 DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4558 return false;
4560 doff = SVAL(inbuf,smb_vwv11);
4562 numtowrite = SVAL(inbuf,smb_vwv10);
4564 if (len > doff && len - doff > 0xFFFF) {
4565 numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4568 if (numtowrite == 0) {
4569 DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4570 return false;
4573 /* Ensure the sizes match up. */
4574 if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4575 /* no pad byte...old smbclient :-( */
4576 DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4577 (unsigned int)doff,
4578 (unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4579 return false;
4582 if (len - doff != numtowrite) {
4583 DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4584 "len = %u, doff = %u, numtowrite = %u\n",
4585 (unsigned int)len,
4586 (unsigned int)doff,
4587 (unsigned int)numtowrite ));
4588 return false;
4591 DEBUG(10,("is_valid_writeX_buffer: true "
4592 "len = %u, doff = %u, numtowrite = %u\n",
4593 (unsigned int)len,
4594 (unsigned int)doff,
4595 (unsigned int)numtowrite ));
4597 return true;
4600 /****************************************************************************
4601 Reply to a write and X.
4602 ****************************************************************************/
4604 void reply_write_and_X(struct smb_request *req)
4606 connection_struct *conn = req->conn;
4607 files_struct *fsp;
4608 struct lock_struct lock;
4609 off_t startpos;
4610 size_t numtowrite;
4611 bool write_through;
4612 ssize_t nwritten;
4613 unsigned int smb_doff;
4614 unsigned int smblen;
4615 const char *data;
4616 NTSTATUS status;
4617 int saved_errno = 0;
4619 START_PROFILE(SMBwriteX);
4621 if ((req->wct != 12) && (req->wct != 14)) {
4622 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4623 goto out;
4626 numtowrite = SVAL(req->vwv+10, 0);
4627 smb_doff = SVAL(req->vwv+11, 0);
4628 smblen = smb_len(req->inbuf);
4630 if (req->unread_bytes > 0xFFFF ||
4631 (smblen > smb_doff &&
4632 smblen - smb_doff > 0xFFFF)) {
4633 numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4636 if (req->unread_bytes) {
4637 /* Can't do a recvfile write on IPC$ */
4638 if (IS_IPC(conn)) {
4639 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4640 goto out;
4642 if (numtowrite != req->unread_bytes) {
4643 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4644 goto out;
4646 } else {
4647 if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4648 smb_doff + numtowrite > smblen) {
4649 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4650 goto out;
4654 /* If it's an IPC, pass off the pipe handler. */
4655 if (IS_IPC(conn)) {
4656 if (req->unread_bytes) {
4657 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4658 goto out;
4660 reply_pipe_write_and_X(req);
4661 goto out;
4664 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4665 startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4666 write_through = BITSETW(req->vwv+7,0);
4668 if (!check_fsp(conn, req, fsp)) {
4669 goto out;
4672 if (!CHECK_WRITE(fsp)) {
4673 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4674 goto out;
4677 data = smb_base(req->inbuf) + smb_doff;
4679 if(req->wct == 14) {
4681 * This is a large offset (64 bit) write.
4683 startpos |= (((off_t)IVAL(req->vwv+12, 0)) << 32);
4687 /* X/Open SMB protocol says that, unlike SMBwrite
4688 if the length is zero then NO truncation is
4689 done, just a write of zero. To truncate a file,
4690 use SMBwrite. */
4692 if(numtowrite == 0) {
4693 nwritten = 0;
4694 } else {
4695 if (req->unread_bytes == 0) {
4696 status = schedule_aio_write_and_X(conn,
4697 req,
4698 fsp,
4699 data,
4700 startpos,
4701 numtowrite);
4703 if (NT_STATUS_IS_OK(status)) {
4704 /* write scheduled - we're done. */
4705 goto out;
4707 if (!NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
4708 /* Real error - report to client. */
4709 reply_nterror(req, status);
4710 goto out;
4712 /* NT_STATUS_RETRY - fall through to sync write. */
4715 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
4716 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4717 &lock);
4719 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4720 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4721 goto out;
4724 nwritten = write_file(req,fsp,data,startpos,numtowrite);
4725 saved_errno = errno;
4727 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4730 if(nwritten < 0) {
4731 reply_nterror(req, map_nt_error_from_unix(saved_errno));
4732 goto out;
4735 if((nwritten == 0) && (numtowrite != 0)) {
4736 reply_nterror(req, NT_STATUS_DISK_FULL);
4737 goto out;
4740 reply_outbuf(req, 6, 0);
4741 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
4742 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
4743 SSVAL(req->outbuf,smb_vwv2,nwritten);
4744 SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4746 DEBUG(3,("writeX %s num=%d wrote=%d\n",
4747 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten));
4749 status = sync_file(conn, fsp, write_through);
4750 if (!NT_STATUS_IS_OK(status)) {
4751 DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4752 fsp_str_dbg(fsp), nt_errstr(status)));
4753 reply_nterror(req, status);
4754 goto out;
4757 END_PROFILE(SMBwriteX);
4758 return;
4760 out:
4761 if (req->unread_bytes) {
4762 /* writeX failed. drain socket. */
4763 if (drain_socket(req->sconn->sock, req->unread_bytes) !=
4764 req->unread_bytes) {
4765 smb_panic("failed to drain pending bytes");
4767 req->unread_bytes = 0;
4770 END_PROFILE(SMBwriteX);
4771 return;
4774 /****************************************************************************
4775 Reply to a lseek.
4776 ****************************************************************************/
4778 void reply_lseek(struct smb_request *req)
4780 connection_struct *conn = req->conn;
4781 off_t startpos;
4782 off_t res= -1;
4783 int mode,umode;
4784 files_struct *fsp;
4786 START_PROFILE(SMBlseek);
4788 if (req->wct < 4) {
4789 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4790 END_PROFILE(SMBlseek);
4791 return;
4794 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4796 if (!check_fsp(conn, req, fsp)) {
4797 return;
4800 flush_write_cache(fsp, SEEK_FLUSH);
4802 mode = SVAL(req->vwv+1, 0) & 3;
4803 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4804 startpos = (off_t)IVALS(req->vwv+2, 0);
4806 switch (mode) {
4807 case 0:
4808 umode = SEEK_SET;
4809 res = startpos;
4810 break;
4811 case 1:
4812 umode = SEEK_CUR;
4813 res = fsp->fh->pos + startpos;
4814 break;
4815 case 2:
4816 umode = SEEK_END;
4817 break;
4818 default:
4819 umode = SEEK_SET;
4820 res = startpos;
4821 break;
4824 if (umode == SEEK_END) {
4825 if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4826 if(errno == EINVAL) {
4827 off_t current_pos = startpos;
4829 if(fsp_stat(fsp) == -1) {
4830 reply_nterror(req,
4831 map_nt_error_from_unix(errno));
4832 END_PROFILE(SMBlseek);
4833 return;
4836 current_pos += fsp->fsp_name->st.st_ex_size;
4837 if(current_pos < 0)
4838 res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4842 if(res == -1) {
4843 reply_nterror(req, map_nt_error_from_unix(errno));
4844 END_PROFILE(SMBlseek);
4845 return;
4849 fsp->fh->pos = res;
4851 reply_outbuf(req, 2, 0);
4852 SIVAL(req->outbuf,smb_vwv0,res);
4854 DEBUG(3,("lseek %s ofs=%.0f newpos = %.0f mode=%d\n",
4855 fsp_fnum_dbg(fsp), (double)startpos, (double)res, mode));
4857 END_PROFILE(SMBlseek);
4858 return;
4861 /****************************************************************************
4862 Reply to a flush.
4863 ****************************************************************************/
4865 void reply_flush(struct smb_request *req)
4867 connection_struct *conn = req->conn;
4868 uint16 fnum;
4869 files_struct *fsp;
4871 START_PROFILE(SMBflush);
4873 if (req->wct < 1) {
4874 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4875 return;
4878 fnum = SVAL(req->vwv+0, 0);
4879 fsp = file_fsp(req, fnum);
4881 if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4882 return;
4885 if (!fsp) {
4886 file_sync_all(conn);
4887 } else {
4888 NTSTATUS status = sync_file(conn, fsp, True);
4889 if (!NT_STATUS_IS_OK(status)) {
4890 DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4891 fsp_str_dbg(fsp), nt_errstr(status)));
4892 reply_nterror(req, status);
4893 END_PROFILE(SMBflush);
4894 return;
4898 reply_outbuf(req, 0, 0);
4900 DEBUG(3,("flush\n"));
4901 END_PROFILE(SMBflush);
4902 return;
4905 /****************************************************************************
4906 Reply to a exit.
4907 conn POINTER CAN BE NULL HERE !
4908 ****************************************************************************/
4910 void reply_exit(struct smb_request *req)
4912 START_PROFILE(SMBexit);
4914 file_close_pid(req->sconn, req->smbpid, req->vuid);
4916 reply_outbuf(req, 0, 0);
4918 DEBUG(3,("exit\n"));
4920 END_PROFILE(SMBexit);
4921 return;
4924 struct reply_close_state {
4925 files_struct *fsp;
4926 struct smb_request *smbreq;
4929 static void do_smb1_close(struct tevent_req *req);
4931 void reply_close(struct smb_request *req)
4933 connection_struct *conn = req->conn;
4934 NTSTATUS status = NT_STATUS_OK;
4935 files_struct *fsp = NULL;
4936 START_PROFILE(SMBclose);
4938 if (req->wct < 3) {
4939 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4940 END_PROFILE(SMBclose);
4941 return;
4944 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4947 * We can only use check_fsp if we know it's not a directory.
4950 if (!check_fsp_open(conn, req, fsp)) {
4951 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4952 END_PROFILE(SMBclose);
4953 return;
4956 DEBUG(3, ("Close %s fd=%d %s (numopen=%d)\n",
4957 fsp->is_directory ? "directory" : "file",
4958 fsp->fh->fd, fsp_fnum_dbg(fsp),
4959 conn->num_files_open));
4961 if (!fsp->is_directory) {
4962 time_t t;
4965 * Take care of any time sent in the close.
4968 t = srv_make_unix_date3(req->vwv+1);
4969 set_close_write_time(fsp, convert_time_t_to_timespec(t));
4972 if (fsp->num_aio_requests != 0) {
4974 struct reply_close_state *state;
4976 DEBUG(10, ("closing with aio %u requests pending\n",
4977 fsp->num_aio_requests));
4980 * We depend on the aio_extra destructor to take care of this
4981 * close request once fsp->num_aio_request drops to 0.
4984 fsp->deferred_close = tevent_wait_send(
4985 fsp, fsp->conn->sconn->ev_ctx);
4986 if (fsp->deferred_close == NULL) {
4987 status = NT_STATUS_NO_MEMORY;
4988 goto done;
4991 state = talloc(fsp, struct reply_close_state);
4992 if (state == NULL) {
4993 TALLOC_FREE(fsp->deferred_close);
4994 status = NT_STATUS_NO_MEMORY;
4995 goto done;
4997 state->fsp = fsp;
4998 state->smbreq = talloc_move(fsp, &req);
4999 tevent_req_set_callback(fsp->deferred_close, do_smb1_close,
5000 state);
5001 END_PROFILE(SMBclose);
5002 return;
5006 * close_file() returns the unix errno if an error was detected on
5007 * close - normally this is due to a disk full error. If not then it
5008 * was probably an I/O error.
5011 status = close_file(req, fsp, NORMAL_CLOSE);
5012 done:
5013 if (!NT_STATUS_IS_OK(status)) {
5014 reply_nterror(req, status);
5015 END_PROFILE(SMBclose);
5016 return;
5019 reply_outbuf(req, 0, 0);
5020 END_PROFILE(SMBclose);
5021 return;
5024 static void do_smb1_close(struct tevent_req *req)
5026 struct reply_close_state *state = tevent_req_callback_data(
5027 req, struct reply_close_state);
5028 struct smb_request *smbreq;
5029 NTSTATUS status;
5030 int ret;
5032 ret = tevent_wait_recv(req);
5033 TALLOC_FREE(req);
5034 if (ret != 0) {
5035 DEBUG(10, ("tevent_wait_recv returned %s\n",
5036 strerror(ret)));
5038 * Continue anyway, this should never happen
5043 * fsp->smb2_close_request right now is a talloc grandchild of
5044 * fsp. When we close_file(fsp), it would go with it. No chance to
5045 * reply...
5047 smbreq = talloc_move(talloc_tos(), &state->smbreq);
5049 status = close_file(smbreq, state->fsp, NORMAL_CLOSE);
5050 if (NT_STATUS_IS_OK(status)) {
5051 reply_outbuf(smbreq, 0, 0);
5052 } else {
5053 reply_nterror(smbreq, status);
5055 if (!srv_send_smb(smbreq->sconn,
5056 (char *)smbreq->outbuf,
5057 true,
5058 smbreq->seqnum+1,
5059 IS_CONN_ENCRYPTED(smbreq->conn)||smbreq->encrypted,
5060 NULL)) {
5061 exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
5062 "failed.");
5064 TALLOC_FREE(smbreq);
5067 /****************************************************************************
5068 Reply to a writeclose (Core+ protocol).
5069 ****************************************************************************/
5071 void reply_writeclose(struct smb_request *req)
5073 connection_struct *conn = req->conn;
5074 size_t numtowrite;
5075 ssize_t nwritten = -1;
5076 NTSTATUS close_status = NT_STATUS_OK;
5077 off_t startpos;
5078 const char *data;
5079 struct timespec mtime;
5080 files_struct *fsp;
5081 struct lock_struct lock;
5083 START_PROFILE(SMBwriteclose);
5085 if (req->wct < 6) {
5086 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5087 END_PROFILE(SMBwriteclose);
5088 return;
5091 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5093 if (!check_fsp(conn, req, fsp)) {
5094 END_PROFILE(SMBwriteclose);
5095 return;
5097 if (!CHECK_WRITE(fsp)) {
5098 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5099 END_PROFILE(SMBwriteclose);
5100 return;
5103 numtowrite = SVAL(req->vwv+1, 0);
5104 startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
5105 mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
5106 data = (const char *)req->buf + 1;
5108 if (!fsp->print_file) {
5109 init_strict_lock_struct(fsp, (uint64_t)req->smbpid,
5110 (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
5111 &lock);
5113 if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
5114 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
5115 END_PROFILE(SMBwriteclose);
5116 return;
5120 nwritten = write_file(req,fsp,data,startpos,numtowrite);
5122 set_close_write_time(fsp, mtime);
5125 * More insanity. W2K only closes the file if writelen > 0.
5126 * JRA.
5129 if (numtowrite) {
5130 DEBUG(3,("reply_writeclose: zero length write doesn't close "
5131 "file %s\n", fsp_str_dbg(fsp)));
5132 close_status = close_file(req, fsp, NORMAL_CLOSE);
5135 DEBUG(3,("writeclose %s num=%d wrote=%d (numopen=%d)\n",
5136 fsp_fnum_dbg(fsp), (int)numtowrite, (int)nwritten,
5137 conn->num_files_open));
5139 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
5140 reply_nterror(req, NT_STATUS_DISK_FULL);
5141 goto strict_unlock;
5144 if(!NT_STATUS_IS_OK(close_status)) {
5145 reply_nterror(req, close_status);
5146 goto strict_unlock;
5149 reply_outbuf(req, 1, 0);
5151 SSVAL(req->outbuf,smb_vwv0,nwritten);
5153 strict_unlock:
5154 if (numtowrite && !fsp->print_file) {
5155 SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
5158 END_PROFILE(SMBwriteclose);
5159 return;
5162 #undef DBGC_CLASS
5163 #define DBGC_CLASS DBGC_LOCKING
5165 /****************************************************************************
5166 Reply to a lock.
5167 ****************************************************************************/
5169 void reply_lock(struct smb_request *req)
5171 connection_struct *conn = req->conn;
5172 uint64_t count,offset;
5173 NTSTATUS status;
5174 files_struct *fsp;
5175 struct byte_range_lock *br_lck = NULL;
5177 START_PROFILE(SMBlock);
5179 if (req->wct < 5) {
5180 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5181 END_PROFILE(SMBlock);
5182 return;
5185 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5187 if (!check_fsp(conn, req, fsp)) {
5188 END_PROFILE(SMBlock);
5189 return;
5192 count = (uint64_t)IVAL(req->vwv+1, 0);
5193 offset = (uint64_t)IVAL(req->vwv+3, 0);
5195 DEBUG(3,("lock fd=%d %s offset=%.0f count=%.0f\n",
5196 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count));
5198 br_lck = do_lock(req->sconn->msg_ctx,
5199 fsp,
5200 (uint64_t)req->smbpid,
5201 count,
5202 offset,
5203 WRITE_LOCK,
5204 WINDOWS_LOCK,
5205 False, /* Non-blocking lock. */
5206 &status,
5207 NULL,
5208 NULL);
5210 TALLOC_FREE(br_lck);
5212 if (NT_STATUS_V(status)) {
5213 reply_nterror(req, status);
5214 END_PROFILE(SMBlock);
5215 return;
5218 reply_outbuf(req, 0, 0);
5220 END_PROFILE(SMBlock);
5221 return;
5224 /****************************************************************************
5225 Reply to a unlock.
5226 ****************************************************************************/
5228 void reply_unlock(struct smb_request *req)
5230 connection_struct *conn = req->conn;
5231 uint64_t count,offset;
5232 NTSTATUS status;
5233 files_struct *fsp;
5235 START_PROFILE(SMBunlock);
5237 if (req->wct < 5) {
5238 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5239 END_PROFILE(SMBunlock);
5240 return;
5243 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5245 if (!check_fsp(conn, req, fsp)) {
5246 END_PROFILE(SMBunlock);
5247 return;
5250 count = (uint64_t)IVAL(req->vwv+1, 0);
5251 offset = (uint64_t)IVAL(req->vwv+3, 0);
5253 status = do_unlock(req->sconn->msg_ctx,
5254 fsp,
5255 (uint64_t)req->smbpid,
5256 count,
5257 offset,
5258 WINDOWS_LOCK);
5260 if (NT_STATUS_V(status)) {
5261 reply_nterror(req, status);
5262 END_PROFILE(SMBunlock);
5263 return;
5266 DEBUG( 3, ( "unlock fd=%d %s offset=%.0f count=%.0f\n",
5267 fsp->fh->fd, fsp_fnum_dbg(fsp), (double)offset, (double)count ) );
5269 reply_outbuf(req, 0, 0);
5271 END_PROFILE(SMBunlock);
5272 return;
5275 #undef DBGC_CLASS
5276 #define DBGC_CLASS DBGC_ALL
5278 /****************************************************************************
5279 Reply to a tdis.
5280 conn POINTER CAN BE NULL HERE !
5281 ****************************************************************************/
5283 void reply_tdis(struct smb_request *req)
5285 NTSTATUS status;
5286 connection_struct *conn = req->conn;
5287 struct smbXsrv_tcon *tcon;
5289 START_PROFILE(SMBtdis);
5291 if (!conn) {
5292 DEBUG(4,("Invalid connection in tdis\n"));
5293 reply_force_doserror(req, ERRSRV, ERRinvnid);
5294 END_PROFILE(SMBtdis);
5295 return;
5298 tcon = conn->tcon;
5299 req->conn = NULL;
5302 * TODO: cancel all outstanding requests on the tcon
5304 status = smbXsrv_tcon_disconnect(tcon, req->vuid);
5305 if (!NT_STATUS_IS_OK(status)) {
5306 DEBUG(0, ("reply_tdis: "
5307 "smbXsrv_tcon_disconnect() failed: %s\n",
5308 nt_errstr(status)));
5310 * If we hit this case, there is something completely
5311 * wrong, so we better disconnect the transport connection.
5313 END_PROFILE(SMBtdis);
5314 exit_server(__location__ ": smbXsrv_tcon_disconnect failed");
5315 return;
5318 TALLOC_FREE(tcon);
5320 reply_outbuf(req, 0, 0);
5321 END_PROFILE(SMBtdis);
5322 return;
5325 /****************************************************************************
5326 Reply to a echo.
5327 conn POINTER CAN BE NULL HERE !
5328 ****************************************************************************/
5330 void reply_echo(struct smb_request *req)
5332 connection_struct *conn = req->conn;
5333 struct smb_perfcount_data local_pcd;
5334 struct smb_perfcount_data *cur_pcd;
5335 int smb_reverb;
5336 int seq_num;
5338 START_PROFILE(SMBecho);
5340 smb_init_perfcount_data(&local_pcd);
5342 if (req->wct < 1) {
5343 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5344 END_PROFILE(SMBecho);
5345 return;
5348 smb_reverb = SVAL(req->vwv+0, 0);
5350 reply_outbuf(req, 1, req->buflen);
5352 /* copy any incoming data back out */
5353 if (req->buflen > 0) {
5354 memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
5357 if (smb_reverb > 100) {
5358 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
5359 smb_reverb = 100;
5362 for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
5364 /* this makes sure we catch the request pcd */
5365 if (seq_num == smb_reverb) {
5366 cur_pcd = &req->pcd;
5367 } else {
5368 SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
5369 cur_pcd = &local_pcd;
5372 SSVAL(req->outbuf,smb_vwv0,seq_num);
5374 show_msg((char *)req->outbuf);
5375 if (!srv_send_smb(req->sconn,
5376 (char *)req->outbuf,
5377 true, req->seqnum+1,
5378 IS_CONN_ENCRYPTED(conn)||req->encrypted,
5379 cur_pcd))
5380 exit_server_cleanly("reply_echo: srv_send_smb failed.");
5383 DEBUG(3,("echo %d times\n", smb_reverb));
5385 TALLOC_FREE(req->outbuf);
5387 END_PROFILE(SMBecho);
5388 return;
5391 /****************************************************************************
5392 Reply to a printopen.
5393 ****************************************************************************/
5395 void reply_printopen(struct smb_request *req)
5397 connection_struct *conn = req->conn;
5398 files_struct *fsp;
5399 NTSTATUS status;
5401 START_PROFILE(SMBsplopen);
5403 if (req->wct < 2) {
5404 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5405 END_PROFILE(SMBsplopen);
5406 return;
5409 if (!CAN_PRINT(conn)) {
5410 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5411 END_PROFILE(SMBsplopen);
5412 return;
5415 status = file_new(req, conn, &fsp);
5416 if(!NT_STATUS_IS_OK(status)) {
5417 reply_nterror(req, status);
5418 END_PROFILE(SMBsplopen);
5419 return;
5422 /* Open for exclusive use, write only. */
5423 status = print_spool_open(fsp, NULL, req->vuid);
5425 if (!NT_STATUS_IS_OK(status)) {
5426 file_free(req, fsp);
5427 reply_nterror(req, status);
5428 END_PROFILE(SMBsplopen);
5429 return;
5432 reply_outbuf(req, 1, 0);
5433 SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5435 DEBUG(3,("openprint fd=%d %s\n",
5436 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5438 END_PROFILE(SMBsplopen);
5439 return;
5442 /****************************************************************************
5443 Reply to a printclose.
5444 ****************************************************************************/
5446 void reply_printclose(struct smb_request *req)
5448 connection_struct *conn = req->conn;
5449 files_struct *fsp;
5450 NTSTATUS status;
5452 START_PROFILE(SMBsplclose);
5454 if (req->wct < 1) {
5455 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5456 END_PROFILE(SMBsplclose);
5457 return;
5460 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5462 if (!check_fsp(conn, req, fsp)) {
5463 END_PROFILE(SMBsplclose);
5464 return;
5467 if (!CAN_PRINT(conn)) {
5468 reply_force_doserror(req, ERRSRV, ERRerror);
5469 END_PROFILE(SMBsplclose);
5470 return;
5473 DEBUG(3,("printclose fd=%d %s\n",
5474 fsp->fh->fd, fsp_fnum_dbg(fsp)));
5476 status = close_file(req, fsp, NORMAL_CLOSE);
5478 if(!NT_STATUS_IS_OK(status)) {
5479 reply_nterror(req, status);
5480 END_PROFILE(SMBsplclose);
5481 return;
5484 reply_outbuf(req, 0, 0);
5486 END_PROFILE(SMBsplclose);
5487 return;
5490 /****************************************************************************
5491 Reply to a printqueue.
5492 ****************************************************************************/
5494 void reply_printqueue(struct smb_request *req)
5496 connection_struct *conn = req->conn;
5497 int max_count;
5498 int start_index;
5500 START_PROFILE(SMBsplretq);
5502 if (req->wct < 2) {
5503 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5504 END_PROFILE(SMBsplretq);
5505 return;
5508 max_count = SVAL(req->vwv+0, 0);
5509 start_index = SVAL(req->vwv+1, 0);
5511 /* we used to allow the client to get the cnum wrong, but that
5512 is really quite gross and only worked when there was only
5513 one printer - I think we should now only accept it if they
5514 get it right (tridge) */
5515 if (!CAN_PRINT(conn)) {
5516 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5517 END_PROFILE(SMBsplretq);
5518 return;
5521 reply_outbuf(req, 2, 3);
5522 SSVAL(req->outbuf,smb_vwv0,0);
5523 SSVAL(req->outbuf,smb_vwv1,0);
5524 SCVAL(smb_buf(req->outbuf),0,1);
5525 SSVAL(smb_buf(req->outbuf),1,0);
5527 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5528 start_index, max_count));
5531 TALLOC_CTX *mem_ctx = talloc_tos();
5532 NTSTATUS status;
5533 WERROR werr;
5534 const char *sharename = lp_servicename(mem_ctx, SNUM(conn));
5535 struct rpc_pipe_client *cli = NULL;
5536 struct dcerpc_binding_handle *b = NULL;
5537 struct policy_handle handle;
5538 struct spoolss_DevmodeContainer devmode_ctr;
5539 union spoolss_JobInfo *info;
5540 uint32_t count;
5541 uint32_t num_to_get;
5542 uint32_t first;
5543 uint32_t i;
5545 ZERO_STRUCT(handle);
5547 status = rpc_pipe_open_interface(conn,
5548 &ndr_table_spoolss.syntax_id,
5549 conn->session_info,
5550 conn->sconn->remote_address,
5551 conn->sconn->msg_ctx,
5552 &cli);
5553 if (!NT_STATUS_IS_OK(status)) {
5554 DEBUG(0, ("reply_printqueue: "
5555 "could not connect to spoolss: %s\n",
5556 nt_errstr(status)));
5557 reply_nterror(req, status);
5558 goto out;
5560 b = cli->binding_handle;
5562 ZERO_STRUCT(devmode_ctr);
5564 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5565 sharename,
5566 NULL, devmode_ctr,
5567 SEC_FLAG_MAXIMUM_ALLOWED,
5568 &handle,
5569 &werr);
5570 if (!NT_STATUS_IS_OK(status)) {
5571 reply_nterror(req, status);
5572 goto out;
5574 if (!W_ERROR_IS_OK(werr)) {
5575 reply_nterror(req, werror_to_ntstatus(werr));
5576 goto out;
5579 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
5580 &handle,
5581 0, /* firstjob */
5582 0xff, /* numjobs */
5583 2, /* level */
5584 0, /* offered */
5585 &count,
5586 &info);
5587 if (!W_ERROR_IS_OK(werr)) {
5588 reply_nterror(req, werror_to_ntstatus(werr));
5589 goto out;
5592 if (max_count > 0) {
5593 first = start_index;
5594 } else {
5595 first = start_index + max_count + 1;
5598 if (first >= count) {
5599 num_to_get = first;
5600 } else {
5601 num_to_get = first + MIN(ABS(max_count), count - first);
5604 for (i = first; i < num_to_get; i++) {
5605 char blob[28];
5606 char *p = blob;
5607 time_t qtime = spoolss_Time_to_time_t(&info[i].info2.submitted);
5608 int qstatus;
5609 uint16_t qrapjobid = pjobid_to_rap(sharename,
5610 info[i].info2.job_id);
5612 if (info[i].info2.status == JOB_STATUS_PRINTING) {
5613 qstatus = 2;
5614 } else {
5615 qstatus = 3;
5618 srv_put_dos_date2(p, 0, qtime);
5619 SCVAL(p, 4, qstatus);
5620 SSVAL(p, 5, qrapjobid);
5621 SIVAL(p, 7, info[i].info2.size);
5622 SCVAL(p, 11, 0);
5623 srvstr_push(blob, req->flags2, p+12,
5624 info[i].info2.notify_name, 16, STR_ASCII);
5626 if (message_push_blob(
5627 &req->outbuf,
5628 data_blob_const(
5629 blob, sizeof(blob))) == -1) {
5630 reply_nterror(req, NT_STATUS_NO_MEMORY);
5631 goto out;
5635 if (count > 0) {
5636 SSVAL(req->outbuf,smb_vwv0,count);
5637 SSVAL(req->outbuf,smb_vwv1,
5638 (max_count>0?first+count:first-1));
5639 SCVAL(smb_buf(req->outbuf),0,1);
5640 SSVAL(smb_buf(req->outbuf),1,28*count);
5644 DEBUG(3, ("%u entries returned in queue\n",
5645 (unsigned)count));
5647 out:
5648 if (b && is_valid_policy_hnd(&handle)) {
5649 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5654 END_PROFILE(SMBsplretq);
5655 return;
5658 /****************************************************************************
5659 Reply to a printwrite.
5660 ****************************************************************************/
5662 void reply_printwrite(struct smb_request *req)
5664 connection_struct *conn = req->conn;
5665 int numtowrite;
5666 const char *data;
5667 files_struct *fsp;
5669 START_PROFILE(SMBsplwr);
5671 if (req->wct < 1) {
5672 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5673 END_PROFILE(SMBsplwr);
5674 return;
5677 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5679 if (!check_fsp(conn, req, fsp)) {
5680 END_PROFILE(SMBsplwr);
5681 return;
5684 if (!fsp->print_file) {
5685 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5686 END_PROFILE(SMBsplwr);
5687 return;
5690 if (!CHECK_WRITE(fsp)) {
5691 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5692 END_PROFILE(SMBsplwr);
5693 return;
5696 numtowrite = SVAL(req->buf, 1);
5698 if (req->buflen < numtowrite + 3) {
5699 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5700 END_PROFILE(SMBsplwr);
5701 return;
5704 data = (const char *)req->buf + 3;
5706 if (write_file(req,fsp,data,(off_t)-1,numtowrite) != numtowrite) {
5707 reply_nterror(req, map_nt_error_from_unix(errno));
5708 END_PROFILE(SMBsplwr);
5709 return;
5712 DEBUG(3, ("printwrite %s num=%d\n", fsp_fnum_dbg(fsp), numtowrite));
5714 END_PROFILE(SMBsplwr);
5715 return;
5718 /****************************************************************************
5719 Reply to a mkdir.
5720 ****************************************************************************/
5722 void reply_mkdir(struct smb_request *req)
5724 connection_struct *conn = req->conn;
5725 struct smb_filename *smb_dname = NULL;
5726 char *directory = NULL;
5727 NTSTATUS status;
5728 TALLOC_CTX *ctx = talloc_tos();
5730 START_PROFILE(SMBmkdir);
5732 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5733 STR_TERMINATE, &status);
5734 if (!NT_STATUS_IS_OK(status)) {
5735 reply_nterror(req, status);
5736 goto out;
5739 status = filename_convert(ctx, conn,
5740 req->flags2 & FLAGS2_DFS_PATHNAMES,
5741 directory,
5743 NULL,
5744 &smb_dname);
5745 if (!NT_STATUS_IS_OK(status)) {
5746 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5747 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5748 ERRSRV, ERRbadpath);
5749 goto out;
5751 reply_nterror(req, status);
5752 goto out;
5755 status = create_directory(conn, req, smb_dname);
5757 DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5759 if (!NT_STATUS_IS_OK(status)) {
5761 if (!use_nt_status()
5762 && NT_STATUS_EQUAL(status,
5763 NT_STATUS_OBJECT_NAME_COLLISION)) {
5765 * Yes, in the DOS error code case we get a
5766 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5767 * samba4 torture test.
5769 status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5772 reply_nterror(req, status);
5773 goto out;
5776 reply_outbuf(req, 0, 0);
5778 DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5779 out:
5780 TALLOC_FREE(smb_dname);
5781 END_PROFILE(SMBmkdir);
5782 return;
5785 /****************************************************************************
5786 Reply to a rmdir.
5787 ****************************************************************************/
5789 void reply_rmdir(struct smb_request *req)
5791 connection_struct *conn = req->conn;
5792 struct smb_filename *smb_dname = NULL;
5793 char *directory = NULL;
5794 NTSTATUS status;
5795 TALLOC_CTX *ctx = talloc_tos();
5796 files_struct *fsp = NULL;
5797 int info = 0;
5798 struct smbd_server_connection *sconn = req->sconn;
5800 START_PROFILE(SMBrmdir);
5802 srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5803 STR_TERMINATE, &status);
5804 if (!NT_STATUS_IS_OK(status)) {
5805 reply_nterror(req, status);
5806 goto out;
5809 status = filename_convert(ctx, conn,
5810 req->flags2 & FLAGS2_DFS_PATHNAMES,
5811 directory,
5813 NULL,
5814 &smb_dname);
5815 if (!NT_STATUS_IS_OK(status)) {
5816 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5817 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5818 ERRSRV, ERRbadpath);
5819 goto out;
5821 reply_nterror(req, status);
5822 goto out;
5825 if (is_ntfs_stream_smb_fname(smb_dname)) {
5826 reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5827 goto out;
5830 status = SMB_VFS_CREATE_FILE(
5831 conn, /* conn */
5832 req, /* req */
5833 0, /* root_dir_fid */
5834 smb_dname, /* fname */
5835 DELETE_ACCESS, /* access_mask */
5836 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5837 FILE_SHARE_DELETE),
5838 FILE_OPEN, /* create_disposition*/
5839 FILE_DIRECTORY_FILE, /* create_options */
5840 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
5841 0, /* oplock_request */
5842 0, /* allocation_size */
5843 0, /* private_flags */
5844 NULL, /* sd */
5845 NULL, /* ea_list */
5846 &fsp, /* result */
5847 &info); /* pinfo */
5849 if (!NT_STATUS_IS_OK(status)) {
5850 if (open_was_deferred(req->sconn, req->mid)) {
5851 /* We have re-scheduled this call. */
5852 goto out;
5854 reply_nterror(req, status);
5855 goto out;
5858 status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5859 if (!NT_STATUS_IS_OK(status)) {
5860 close_file(req, fsp, ERROR_CLOSE);
5861 reply_nterror(req, status);
5862 goto out;
5865 if (!set_delete_on_close(fsp, true,
5866 conn->session_info->security_token,
5867 conn->session_info->unix_token)) {
5868 close_file(req, fsp, ERROR_CLOSE);
5869 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5870 goto out;
5873 status = close_file(req, fsp, NORMAL_CLOSE);
5874 if (!NT_STATUS_IS_OK(status)) {
5875 reply_nterror(req, status);
5876 } else {
5877 reply_outbuf(req, 0, 0);
5880 dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5882 DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5883 out:
5884 TALLOC_FREE(smb_dname);
5885 END_PROFILE(SMBrmdir);
5886 return;
5889 /*******************************************************************
5890 Resolve wildcards in a filename rename.
5891 ********************************************************************/
5893 static bool resolve_wildcards(TALLOC_CTX *ctx,
5894 const char *name1,
5895 const char *name2,
5896 char **pp_newname)
5898 char *name2_copy = NULL;
5899 char *root1 = NULL;
5900 char *root2 = NULL;
5901 char *ext1 = NULL;
5902 char *ext2 = NULL;
5903 char *p,*p2, *pname1, *pname2;
5905 name2_copy = talloc_strdup(ctx, name2);
5906 if (!name2_copy) {
5907 return False;
5910 pname1 = strrchr_m(name1,'/');
5911 pname2 = strrchr_m(name2_copy,'/');
5913 if (!pname1 || !pname2) {
5914 return False;
5917 /* Truncate the copy of name2 at the last '/' */
5918 *pname2 = '\0';
5920 /* Now go past the '/' */
5921 pname1++;
5922 pname2++;
5924 root1 = talloc_strdup(ctx, pname1);
5925 root2 = talloc_strdup(ctx, pname2);
5927 if (!root1 || !root2) {
5928 return False;
5931 p = strrchr_m(root1,'.');
5932 if (p) {
5933 *p = 0;
5934 ext1 = talloc_strdup(ctx, p+1);
5935 } else {
5936 ext1 = talloc_strdup(ctx, "");
5938 p = strrchr_m(root2,'.');
5939 if (p) {
5940 *p = 0;
5941 ext2 = talloc_strdup(ctx, p+1);
5942 } else {
5943 ext2 = talloc_strdup(ctx, "");
5946 if (!ext1 || !ext2) {
5947 return False;
5950 p = root1;
5951 p2 = root2;
5952 while (*p2) {
5953 if (*p2 == '?') {
5954 /* Hmmm. Should this be mb-aware ? */
5955 *p2 = *p;
5956 p2++;
5957 } else if (*p2 == '*') {
5958 *p2 = '\0';
5959 root2 = talloc_asprintf(ctx, "%s%s",
5960 root2,
5962 if (!root2) {
5963 return False;
5965 break;
5966 } else {
5967 p2++;
5969 if (*p) {
5970 p++;
5974 p = ext1;
5975 p2 = ext2;
5976 while (*p2) {
5977 if (*p2 == '?') {
5978 /* Hmmm. Should this be mb-aware ? */
5979 *p2 = *p;
5980 p2++;
5981 } else if (*p2 == '*') {
5982 *p2 = '\0';
5983 ext2 = talloc_asprintf(ctx, "%s%s",
5984 ext2,
5986 if (!ext2) {
5987 return False;
5989 break;
5990 } else {
5991 p2++;
5993 if (*p) {
5994 p++;
5998 if (*ext2) {
5999 *pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
6000 name2_copy,
6001 root2,
6002 ext2);
6003 } else {
6004 *pp_newname = talloc_asprintf(ctx, "%s/%s",
6005 name2_copy,
6006 root2);
6009 if (!*pp_newname) {
6010 return False;
6013 return True;
6016 /****************************************************************************
6017 Ensure open files have their names updated. Updated to notify other smbd's
6018 asynchronously.
6019 ****************************************************************************/
6021 static void rename_open_files(connection_struct *conn,
6022 struct share_mode_lock *lck,
6023 uint32_t orig_name_hash,
6024 const struct smb_filename *smb_fname_dst)
6026 files_struct *fsp;
6027 bool did_rename = False;
6028 NTSTATUS status;
6029 uint32_t new_name_hash = 0;
6031 for(fsp = file_find_di_first(conn->sconn, lck->data->id); fsp;
6032 fsp = file_find_di_next(fsp)) {
6033 /* fsp_name is a relative path under the fsp. To change this for other
6034 sharepaths we need to manipulate relative paths. */
6035 /* TODO - create the absolute path and manipulate the newname
6036 relative to the sharepath. */
6037 if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
6038 continue;
6040 if (fsp->name_hash != orig_name_hash) {
6041 continue;
6043 DEBUG(10, ("rename_open_files: renaming file %s "
6044 "(file_id %s) from %s -> %s\n", fsp_fnum_dbg(fsp),
6045 file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
6046 smb_fname_str_dbg(smb_fname_dst)));
6048 status = fsp_set_smb_fname(fsp, smb_fname_dst);
6049 if (NT_STATUS_IS_OK(status)) {
6050 did_rename = True;
6051 new_name_hash = fsp->name_hash;
6055 if (!did_rename) {
6056 DEBUG(10, ("rename_open_files: no open files on file_id %s "
6057 "for %s\n", file_id_string_tos(&lck->data->id),
6058 smb_fname_str_dbg(smb_fname_dst)));
6061 /* Send messages to all smbd's (not ourself) that the name has changed. */
6062 rename_share_filename(conn->sconn->msg_ctx, lck, conn->connectpath,
6063 orig_name_hash, new_name_hash,
6064 smb_fname_dst);
6068 /****************************************************************************
6069 We need to check if the source path is a parent directory of the destination
6070 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
6071 refuse the rename with a sharing violation. Under UNIX the above call can
6072 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
6073 probably need to check that the client is a Windows one before disallowing
6074 this as a UNIX client (one with UNIX extensions) can know the source is a
6075 symlink and make this decision intelligently. Found by an excellent bug
6076 report from <AndyLiebman@aol.com>.
6077 ****************************************************************************/
6079 static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
6080 const struct smb_filename *smb_fname_dst)
6082 const char *psrc = smb_fname_src->base_name;
6083 const char *pdst = smb_fname_dst->base_name;
6084 size_t slen;
6086 if (psrc[0] == '.' && psrc[1] == '/') {
6087 psrc += 2;
6089 if (pdst[0] == '.' && pdst[1] == '/') {
6090 pdst += 2;
6092 if ((slen = strlen(psrc)) > strlen(pdst)) {
6093 return False;
6095 return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
6099 * Do the notify calls from a rename
6102 static void notify_rename(connection_struct *conn, bool is_dir,
6103 const struct smb_filename *smb_fname_src,
6104 const struct smb_filename *smb_fname_dst)
6106 char *parent_dir_src = NULL;
6107 char *parent_dir_dst = NULL;
6108 uint32 mask;
6110 mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
6111 : FILE_NOTIFY_CHANGE_FILE_NAME;
6113 if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
6114 &parent_dir_src, NULL) ||
6115 !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
6116 &parent_dir_dst, NULL)) {
6117 goto out;
6120 if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
6121 notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
6122 smb_fname_src->base_name);
6123 notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
6124 smb_fname_dst->base_name);
6126 else {
6127 notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
6128 smb_fname_src->base_name);
6129 notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
6130 smb_fname_dst->base_name);
6133 /* this is a strange one. w2k3 gives an additional event for
6134 CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
6135 files, but not directories */
6136 if (!is_dir) {
6137 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6138 FILE_NOTIFY_CHANGE_ATTRIBUTES
6139 |FILE_NOTIFY_CHANGE_CREATION,
6140 smb_fname_dst->base_name);
6142 out:
6143 TALLOC_FREE(parent_dir_src);
6144 TALLOC_FREE(parent_dir_dst);
6147 /****************************************************************************
6148 Returns an error if the parent directory for a filename is open in an
6149 incompatible way.
6150 ****************************************************************************/
6152 static NTSTATUS parent_dirname_compatible_open(connection_struct *conn,
6153 const struct smb_filename *smb_fname_dst_in)
6155 char *parent_dir = NULL;
6156 struct smb_filename smb_fname_parent;
6157 struct file_id id;
6158 files_struct *fsp = NULL;
6159 int ret;
6161 if (!parent_dirname(talloc_tos(), smb_fname_dst_in->base_name,
6162 &parent_dir, NULL)) {
6163 return NT_STATUS_NO_MEMORY;
6165 ZERO_STRUCT(smb_fname_parent);
6166 smb_fname_parent.base_name = parent_dir;
6168 ret = SMB_VFS_LSTAT(conn, &smb_fname_parent);
6169 if (ret == -1) {
6170 return map_nt_error_from_unix(errno);
6174 * We're only checking on this smbd here, mostly good
6175 * enough.. and will pass tests.
6178 id = vfs_file_id_from_sbuf(conn, &smb_fname_parent.st);
6179 for (fsp = file_find_di_first(conn->sconn, id); fsp;
6180 fsp = file_find_di_next(fsp)) {
6181 if (fsp->access_mask & DELETE_ACCESS) {
6182 return NT_STATUS_SHARING_VIOLATION;
6185 return NT_STATUS_OK;
6188 /****************************************************************************
6189 Rename an open file - given an fsp.
6190 ****************************************************************************/
6192 NTSTATUS rename_internals_fsp(connection_struct *conn,
6193 files_struct *fsp,
6194 const struct smb_filename *smb_fname_dst_in,
6195 uint32 attrs,
6196 bool replace_if_exists)
6198 TALLOC_CTX *ctx = talloc_tos();
6199 struct smb_filename *smb_fname_dst = NULL;
6200 NTSTATUS status = NT_STATUS_OK;
6201 struct share_mode_lock *lck = NULL;
6202 bool dst_exists, old_is_stream, new_is_stream;
6204 status = check_name(conn, smb_fname_dst_in->base_name);
6205 if (!NT_STATUS_IS_OK(status)) {
6206 return status;
6209 status = parent_dirname_compatible_open(conn, smb_fname_dst_in);
6210 if (!NT_STATUS_IS_OK(status)) {
6211 return status;
6214 /* Make a copy of the dst smb_fname structs */
6216 status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
6217 if (!NT_STATUS_IS_OK(status)) {
6218 goto out;
6222 * Check for special case with case preserving and not
6223 * case sensitive. If the old last component differs from the original
6224 * last component only by case, then we should allow
6225 * the rename (user is trying to change the case of the
6226 * filename).
6228 if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
6229 strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6230 strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
6231 char *last_slash;
6232 char *fname_dst_lcomp_base_mod = NULL;
6233 struct smb_filename *smb_fname_orig_lcomp = NULL;
6236 * Get the last component of the destination name.
6238 last_slash = strrchr_m(smb_fname_dst->base_name, '/');
6239 if (last_slash) {
6240 fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
6241 } else {
6242 fname_dst_lcomp_base_mod = talloc_strdup(ctx, smb_fname_dst->base_name);
6244 if (!fname_dst_lcomp_base_mod) {
6245 status = NT_STATUS_NO_MEMORY;
6246 goto out;
6250 * Create an smb_filename struct using the original last
6251 * component of the destination.
6253 status = create_synthetic_smb_fname_split(ctx,
6254 smb_fname_dst->original_lcomp, NULL,
6255 &smb_fname_orig_lcomp);
6256 if (!NT_STATUS_IS_OK(status)) {
6257 TALLOC_FREE(fname_dst_lcomp_base_mod);
6258 goto out;
6261 /* If the base names only differ by case, use original. */
6262 if(!strcsequal(fname_dst_lcomp_base_mod,
6263 smb_fname_orig_lcomp->base_name)) {
6264 char *tmp;
6266 * Replace the modified last component with the
6267 * original.
6269 if (last_slash) {
6270 *last_slash = '\0'; /* Truncate at the '/' */
6271 tmp = talloc_asprintf(smb_fname_dst,
6272 "%s/%s",
6273 smb_fname_dst->base_name,
6274 smb_fname_orig_lcomp->base_name);
6275 } else {
6276 tmp = talloc_asprintf(smb_fname_dst,
6277 "%s",
6278 smb_fname_orig_lcomp->base_name);
6280 if (tmp == NULL) {
6281 status = NT_STATUS_NO_MEMORY;
6282 TALLOC_FREE(fname_dst_lcomp_base_mod);
6283 TALLOC_FREE(smb_fname_orig_lcomp);
6284 goto out;
6286 TALLOC_FREE(smb_fname_dst->base_name);
6287 smb_fname_dst->base_name = tmp;
6290 /* If the stream_names only differ by case, use original. */
6291 if(!strcsequal(smb_fname_dst->stream_name,
6292 smb_fname_orig_lcomp->stream_name)) {
6293 char *tmp = NULL;
6294 /* Use the original stream. */
6295 tmp = talloc_strdup(smb_fname_dst,
6296 smb_fname_orig_lcomp->stream_name);
6297 if (tmp == NULL) {
6298 status = NT_STATUS_NO_MEMORY;
6299 TALLOC_FREE(fname_dst_lcomp_base_mod);
6300 TALLOC_FREE(smb_fname_orig_lcomp);
6301 goto out;
6303 TALLOC_FREE(smb_fname_dst->stream_name);
6304 smb_fname_dst->stream_name = tmp;
6306 TALLOC_FREE(fname_dst_lcomp_base_mod);
6307 TALLOC_FREE(smb_fname_orig_lcomp);
6311 * If the src and dest names are identical - including case,
6312 * don't do the rename, just return success.
6315 if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
6316 strcsequal(fsp->fsp_name->stream_name,
6317 smb_fname_dst->stream_name)) {
6318 DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
6319 "- returning success\n",
6320 smb_fname_str_dbg(smb_fname_dst)));
6321 status = NT_STATUS_OK;
6322 goto out;
6325 old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
6326 new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
6328 /* Return the correct error code if both names aren't streams. */
6329 if (!old_is_stream && new_is_stream) {
6330 status = NT_STATUS_OBJECT_NAME_INVALID;
6331 goto out;
6334 if (old_is_stream && !new_is_stream) {
6335 status = NT_STATUS_INVALID_PARAMETER;
6336 goto out;
6339 dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
6341 if(!replace_if_exists && dst_exists) {
6342 DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
6343 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6344 smb_fname_str_dbg(smb_fname_dst)));
6345 status = NT_STATUS_OBJECT_NAME_COLLISION;
6346 goto out;
6349 if (dst_exists) {
6350 struct file_id fileid = vfs_file_id_from_sbuf(conn,
6351 &smb_fname_dst->st);
6352 files_struct *dst_fsp = file_find_di_first(conn->sconn,
6353 fileid);
6354 /* The file can be open when renaming a stream */
6355 if (dst_fsp && !new_is_stream) {
6356 DEBUG(3, ("rename_internals_fsp: Target file open\n"));
6357 status = NT_STATUS_ACCESS_DENIED;
6358 goto out;
6362 /* Ensure we have a valid stat struct for the source. */
6363 status = vfs_stat_fsp(fsp);
6364 if (!NT_STATUS_IS_OK(status)) {
6365 goto out;
6368 status = can_rename(conn, fsp, attrs);
6370 if (!NT_STATUS_IS_OK(status)) {
6371 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6372 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6373 smb_fname_str_dbg(smb_fname_dst)));
6374 if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
6375 status = NT_STATUS_ACCESS_DENIED;
6376 goto out;
6379 if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
6380 status = NT_STATUS_ACCESS_DENIED;
6383 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
6386 * We have the file open ourselves, so not being able to get the
6387 * corresponding share mode lock is a fatal error.
6390 SMB_ASSERT(lck != NULL);
6392 if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
6393 uint32 create_options = fsp->fh->private_options;
6395 DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
6396 "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
6397 smb_fname_str_dbg(smb_fname_dst)));
6399 if (!lp_posix_pathnames() &&
6400 (lp_map_archive(SNUM(conn)) ||
6401 lp_store_dos_attributes(SNUM(conn)))) {
6402 /* We must set the archive bit on the newly
6403 renamed file. */
6404 if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
6405 uint32_t old_dosmode = dos_mode(conn,
6406 smb_fname_dst);
6407 file_set_dosmode(conn,
6408 smb_fname_dst,
6409 old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
6410 NULL,
6411 true);
6415 notify_rename(conn, fsp->is_directory, fsp->fsp_name,
6416 smb_fname_dst);
6418 rename_open_files(conn, lck, fsp->name_hash, smb_fname_dst);
6421 * A rename acts as a new file create w.r.t. allowing an initial delete
6422 * on close, probably because in Windows there is a new handle to the
6423 * new file. If initial delete on close was requested but not
6424 * originally set, we need to set it here. This is probably not 100% correct,
6425 * but will work for the CIFSFS client which in non-posix mode
6426 * depends on these semantics. JRA.
6429 if (create_options & FILE_DELETE_ON_CLOSE) {
6430 status = can_set_delete_on_close(fsp, 0);
6432 if (NT_STATUS_IS_OK(status)) {
6433 /* Note that here we set the *inital* delete on close flag,
6434 * not the regular one. The magic gets handled in close. */
6435 fsp->initial_delete_on_close = True;
6438 TALLOC_FREE(lck);
6439 status = NT_STATUS_OK;
6440 goto out;
6443 TALLOC_FREE(lck);
6445 if (errno == ENOTDIR || errno == EISDIR) {
6446 status = NT_STATUS_OBJECT_NAME_COLLISION;
6447 } else {
6448 status = map_nt_error_from_unix(errno);
6451 DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
6452 nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
6453 smb_fname_str_dbg(smb_fname_dst)));
6455 out:
6456 TALLOC_FREE(smb_fname_dst);
6458 return status;
6461 /****************************************************************************
6462 The guts of the rename command, split out so it may be called by the NT SMB
6463 code.
6464 ****************************************************************************/
6466 NTSTATUS rename_internals(TALLOC_CTX *ctx,
6467 connection_struct *conn,
6468 struct smb_request *req,
6469 struct smb_filename *smb_fname_src,
6470 struct smb_filename *smb_fname_dst,
6471 uint32 attrs,
6472 bool replace_if_exists,
6473 bool src_has_wild,
6474 bool dest_has_wild,
6475 uint32_t access_mask)
6477 char *fname_src_dir = NULL;
6478 char *fname_src_mask = NULL;
6479 int count=0;
6480 NTSTATUS status = NT_STATUS_OK;
6481 struct smb_Dir *dir_hnd = NULL;
6482 const char *dname = NULL;
6483 char *talloced = NULL;
6484 long offset = 0;
6485 int create_options = 0;
6486 bool posix_pathnames = lp_posix_pathnames();
6489 * Split the old name into directory and last component
6490 * strings. Note that unix_convert may have stripped off a
6491 * leading ./ from both name and newname if the rename is
6492 * at the root of the share. We need to make sure either both
6493 * name and newname contain a / character or neither of them do
6494 * as this is checked in resolve_wildcards().
6497 /* Split up the directory from the filename/mask. */
6498 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6499 &fname_src_dir, &fname_src_mask);
6500 if (!NT_STATUS_IS_OK(status)) {
6501 status = NT_STATUS_NO_MEMORY;
6502 goto out;
6506 * We should only check the mangled cache
6507 * here if unix_convert failed. This means
6508 * that the path in 'mask' doesn't exist
6509 * on the file system and so we need to look
6510 * for a possible mangle. This patch from
6511 * Tine Smukavec <valentin.smukavec@hermes.si>.
6514 if (!VALID_STAT(smb_fname_src->st) &&
6515 mangle_is_mangled(fname_src_mask, conn->params)) {
6516 char *new_mask = NULL;
6517 mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
6518 conn->params);
6519 if (new_mask) {
6520 TALLOC_FREE(fname_src_mask);
6521 fname_src_mask = new_mask;
6525 if (!src_has_wild) {
6526 files_struct *fsp;
6529 * Only one file needs to be renamed. Append the mask back
6530 * onto the directory.
6532 TALLOC_FREE(smb_fname_src->base_name);
6533 if (ISDOT(fname_src_dir)) {
6534 /* Ensure we use canonical names on open. */
6535 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6536 "%s",
6537 fname_src_mask);
6538 } else {
6539 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6540 "%s/%s",
6541 fname_src_dir,
6542 fname_src_mask);
6544 if (!smb_fname_src->base_name) {
6545 status = NT_STATUS_NO_MEMORY;
6546 goto out;
6549 DEBUG(3, ("rename_internals: case_sensitive = %d, "
6550 "case_preserve = %d, short case preserve = %d, "
6551 "directory = %s, newname = %s, "
6552 "last_component_dest = %s\n",
6553 conn->case_sensitive, conn->case_preserve,
6554 conn->short_case_preserve,
6555 smb_fname_str_dbg(smb_fname_src),
6556 smb_fname_str_dbg(smb_fname_dst),
6557 smb_fname_dst->original_lcomp));
6559 /* The dest name still may have wildcards. */
6560 if (dest_has_wild) {
6561 char *fname_dst_mod = NULL;
6562 if (!resolve_wildcards(smb_fname_dst,
6563 smb_fname_src->base_name,
6564 smb_fname_dst->base_name,
6565 &fname_dst_mod)) {
6566 DEBUG(6, ("rename_internals: resolve_wildcards "
6567 "%s %s failed\n",
6568 smb_fname_src->base_name,
6569 smb_fname_dst->base_name));
6570 status = NT_STATUS_NO_MEMORY;
6571 goto out;
6573 TALLOC_FREE(smb_fname_dst->base_name);
6574 smb_fname_dst->base_name = fname_dst_mod;
6577 ZERO_STRUCT(smb_fname_src->st);
6578 if (posix_pathnames) {
6579 SMB_VFS_LSTAT(conn, smb_fname_src);
6580 } else {
6581 SMB_VFS_STAT(conn, smb_fname_src);
6584 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6585 create_options |= FILE_DIRECTORY_FILE;
6588 status = SMB_VFS_CREATE_FILE(
6589 conn, /* conn */
6590 req, /* req */
6591 0, /* root_dir_fid */
6592 smb_fname_src, /* fname */
6593 access_mask, /* access_mask */
6594 (FILE_SHARE_READ | /* share_access */
6595 FILE_SHARE_WRITE),
6596 FILE_OPEN, /* create_disposition*/
6597 create_options, /* create_options */
6598 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6599 0, /* oplock_request */
6600 0, /* allocation_size */
6601 0, /* private_flags */
6602 NULL, /* sd */
6603 NULL, /* ea_list */
6604 &fsp, /* result */
6605 NULL); /* pinfo */
6607 if (!NT_STATUS_IS_OK(status)) {
6608 DEBUG(3, ("Could not open rename source %s: %s\n",
6609 smb_fname_str_dbg(smb_fname_src),
6610 nt_errstr(status)));
6611 goto out;
6614 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6615 attrs, replace_if_exists);
6617 close_file(req, fsp, NORMAL_CLOSE);
6619 DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6620 nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6621 smb_fname_str_dbg(smb_fname_dst)));
6623 goto out;
6627 * Wildcards - process each file that matches.
6629 if (strequal(fname_src_mask, "????????.???")) {
6630 TALLOC_FREE(fname_src_mask);
6631 fname_src_mask = talloc_strdup(ctx, "*");
6632 if (!fname_src_mask) {
6633 status = NT_STATUS_NO_MEMORY;
6634 goto out;
6638 status = check_name(conn, fname_src_dir);
6639 if (!NT_STATUS_IS_OK(status)) {
6640 goto out;
6643 dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6644 attrs);
6645 if (dir_hnd == NULL) {
6646 status = map_nt_error_from_unix(errno);
6647 goto out;
6650 status = NT_STATUS_NO_SUCH_FILE;
6652 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6653 * - gentest fix. JRA
6656 while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6657 &talloced))) {
6658 files_struct *fsp = NULL;
6659 char *destname = NULL;
6660 bool sysdir_entry = False;
6662 /* Quick check for "." and ".." */
6663 if (ISDOT(dname) || ISDOTDOT(dname)) {
6664 if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
6665 sysdir_entry = True;
6666 } else {
6667 TALLOC_FREE(talloced);
6668 continue;
6672 if (!is_visible_file(conn, fname_src_dir, dname,
6673 &smb_fname_src->st, false)) {
6674 TALLOC_FREE(talloced);
6675 continue;
6678 if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6679 TALLOC_FREE(talloced);
6680 continue;
6683 if (sysdir_entry) {
6684 status = NT_STATUS_OBJECT_NAME_INVALID;
6685 break;
6688 TALLOC_FREE(smb_fname_src->base_name);
6689 if (ISDOT(fname_src_dir)) {
6690 /* Ensure we use canonical names on open. */
6691 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6692 "%s",
6693 dname);
6694 } else {
6695 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6696 "%s/%s",
6697 fname_src_dir,
6698 dname);
6700 if (!smb_fname_src->base_name) {
6701 status = NT_STATUS_NO_MEMORY;
6702 goto out;
6705 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6706 smb_fname_dst->base_name,
6707 &destname)) {
6708 DEBUG(6, ("resolve_wildcards %s %s failed\n",
6709 smb_fname_src->base_name, destname));
6710 TALLOC_FREE(talloced);
6711 continue;
6713 if (!destname) {
6714 status = NT_STATUS_NO_MEMORY;
6715 goto out;
6718 TALLOC_FREE(smb_fname_dst->base_name);
6719 smb_fname_dst->base_name = destname;
6721 ZERO_STRUCT(smb_fname_src->st);
6722 if (posix_pathnames) {
6723 SMB_VFS_LSTAT(conn, smb_fname_src);
6724 } else {
6725 SMB_VFS_STAT(conn, smb_fname_src);
6728 create_options = 0;
6730 if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6731 create_options |= FILE_DIRECTORY_FILE;
6734 status = SMB_VFS_CREATE_FILE(
6735 conn, /* conn */
6736 req, /* req */
6737 0, /* root_dir_fid */
6738 smb_fname_src, /* fname */
6739 access_mask, /* access_mask */
6740 (FILE_SHARE_READ | /* share_access */
6741 FILE_SHARE_WRITE),
6742 FILE_OPEN, /* create_disposition*/
6743 create_options, /* create_options */
6744 posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6745 0, /* oplock_request */
6746 0, /* allocation_size */
6747 0, /* private_flags */
6748 NULL, /* sd */
6749 NULL, /* ea_list */
6750 &fsp, /* result */
6751 NULL); /* pinfo */
6753 if (!NT_STATUS_IS_OK(status)) {
6754 DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6755 "returned %s rename %s -> %s\n",
6756 nt_errstr(status),
6757 smb_fname_str_dbg(smb_fname_src),
6758 smb_fname_str_dbg(smb_fname_dst)));
6759 break;
6762 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6763 dname);
6764 if (!smb_fname_dst->original_lcomp) {
6765 status = NT_STATUS_NO_MEMORY;
6766 goto out;
6769 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6770 attrs, replace_if_exists);
6772 close_file(req, fsp, NORMAL_CLOSE);
6774 if (!NT_STATUS_IS_OK(status)) {
6775 DEBUG(3, ("rename_internals_fsp returned %s for "
6776 "rename %s -> %s\n", nt_errstr(status),
6777 smb_fname_str_dbg(smb_fname_src),
6778 smb_fname_str_dbg(smb_fname_dst)));
6779 break;
6782 count++;
6784 DEBUG(3,("rename_internals: doing rename on %s -> "
6785 "%s\n", smb_fname_str_dbg(smb_fname_src),
6786 smb_fname_str_dbg(smb_fname_src)));
6787 TALLOC_FREE(talloced);
6789 TALLOC_FREE(dir_hnd);
6791 if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6792 status = map_nt_error_from_unix(errno);
6795 out:
6796 TALLOC_FREE(talloced);
6797 TALLOC_FREE(fname_src_dir);
6798 TALLOC_FREE(fname_src_mask);
6799 return status;
6802 /****************************************************************************
6803 Reply to a mv.
6804 ****************************************************************************/
6806 void reply_mv(struct smb_request *req)
6808 connection_struct *conn = req->conn;
6809 char *name = NULL;
6810 char *newname = NULL;
6811 const char *p;
6812 uint32 attrs;
6813 NTSTATUS status;
6814 bool src_has_wcard = False;
6815 bool dest_has_wcard = False;
6816 TALLOC_CTX *ctx = talloc_tos();
6817 struct smb_filename *smb_fname_src = NULL;
6818 struct smb_filename *smb_fname_dst = NULL;
6819 uint32_t src_ucf_flags = lp_posix_pathnames() ? UCF_UNIX_NAME_LOOKUP : UCF_COND_ALLOW_WCARD_LCOMP;
6820 uint32_t dst_ucf_flags = UCF_SAVE_LCOMP | (lp_posix_pathnames() ? 0 : UCF_COND_ALLOW_WCARD_LCOMP);
6821 bool stream_rename = false;
6823 START_PROFILE(SMBmv);
6825 if (req->wct < 1) {
6826 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6827 goto out;
6830 attrs = SVAL(req->vwv+0, 0);
6832 p = (const char *)req->buf + 1;
6833 p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6834 &status, &src_has_wcard);
6835 if (!NT_STATUS_IS_OK(status)) {
6836 reply_nterror(req, status);
6837 goto out;
6839 p++;
6840 p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6841 &status, &dest_has_wcard);
6842 if (!NT_STATUS_IS_OK(status)) {
6843 reply_nterror(req, status);
6844 goto out;
6847 if (!lp_posix_pathnames()) {
6848 /* The newname must begin with a ':' if the
6849 name contains a ':'. */
6850 if (strchr_m(name, ':')) {
6851 if (newname[0] != ':') {
6852 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6853 goto out;
6855 stream_rename = true;
6859 status = filename_convert(ctx,
6860 conn,
6861 req->flags2 & FLAGS2_DFS_PATHNAMES,
6862 name,
6863 src_ucf_flags,
6864 &src_has_wcard,
6865 &smb_fname_src);
6867 if (!NT_STATUS_IS_OK(status)) {
6868 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6869 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6870 ERRSRV, ERRbadpath);
6871 goto out;
6873 reply_nterror(req, status);
6874 goto out;
6877 status = filename_convert(ctx,
6878 conn,
6879 req->flags2 & FLAGS2_DFS_PATHNAMES,
6880 newname,
6881 dst_ucf_flags,
6882 &dest_has_wcard,
6883 &smb_fname_dst);
6885 if (!NT_STATUS_IS_OK(status)) {
6886 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6887 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6888 ERRSRV, ERRbadpath);
6889 goto out;
6891 reply_nterror(req, status);
6892 goto out;
6895 if (stream_rename) {
6896 /* smb_fname_dst->base_name must be the same as
6897 smb_fname_src->base_name. */
6898 TALLOC_FREE(smb_fname_dst->base_name);
6899 smb_fname_dst->base_name = talloc_strdup(smb_fname_dst,
6900 smb_fname_src->base_name);
6901 if (!smb_fname_dst->base_name) {
6902 reply_nterror(req, NT_STATUS_NO_MEMORY);
6903 goto out;
6907 DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6908 smb_fname_str_dbg(smb_fname_dst)));
6910 status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6911 attrs, False, src_has_wcard, dest_has_wcard,
6912 DELETE_ACCESS);
6913 if (!NT_STATUS_IS_OK(status)) {
6914 if (open_was_deferred(req->sconn, req->mid)) {
6915 /* We have re-scheduled this call. */
6916 goto out;
6918 reply_nterror(req, status);
6919 goto out;
6922 reply_outbuf(req, 0, 0);
6923 out:
6924 TALLOC_FREE(smb_fname_src);
6925 TALLOC_FREE(smb_fname_dst);
6926 END_PROFILE(SMBmv);
6927 return;
6930 /*******************************************************************
6931 Copy a file as part of a reply_copy.
6932 ******************************************************************/
6935 * TODO: check error codes on all callers
6938 NTSTATUS copy_file(TALLOC_CTX *ctx,
6939 connection_struct *conn,
6940 struct smb_filename *smb_fname_src,
6941 struct smb_filename *smb_fname_dst,
6942 int ofun,
6943 int count,
6944 bool target_is_directory)
6946 struct smb_filename *smb_fname_dst_tmp = NULL;
6947 off_t ret=-1;
6948 files_struct *fsp1,*fsp2;
6949 uint32 dosattrs;
6950 uint32 new_create_disposition;
6951 NTSTATUS status;
6954 status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6955 if (!NT_STATUS_IS_OK(status)) {
6956 return status;
6960 * If the target is a directory, extract the last component from the
6961 * src filename and append it to the dst filename
6963 if (target_is_directory) {
6964 const char *p;
6966 /* dest/target can't be a stream if it's a directory. */
6967 SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6969 p = strrchr_m(smb_fname_src->base_name,'/');
6970 if (p) {
6971 p++;
6972 } else {
6973 p = smb_fname_src->base_name;
6975 smb_fname_dst_tmp->base_name =
6976 talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6978 if (!smb_fname_dst_tmp->base_name) {
6979 status = NT_STATUS_NO_MEMORY;
6980 goto out;
6984 status = vfs_file_exist(conn, smb_fname_src);
6985 if (!NT_STATUS_IS_OK(status)) {
6986 goto out;
6989 if (!target_is_directory && count) {
6990 new_create_disposition = FILE_OPEN;
6991 } else {
6992 if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
6993 0, ofun,
6994 NULL, NULL,
6995 &new_create_disposition,
6996 NULL,
6997 NULL)) {
6998 status = NT_STATUS_INVALID_PARAMETER;
6999 goto out;
7003 /* Open the src file for reading. */
7004 status = SMB_VFS_CREATE_FILE(
7005 conn, /* conn */
7006 NULL, /* req */
7007 0, /* root_dir_fid */
7008 smb_fname_src, /* fname */
7009 FILE_GENERIC_READ, /* access_mask */
7010 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7011 FILE_OPEN, /* create_disposition*/
7012 0, /* create_options */
7013 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7014 INTERNAL_OPEN_ONLY, /* oplock_request */
7015 0, /* allocation_size */
7016 0, /* private_flags */
7017 NULL, /* sd */
7018 NULL, /* ea_list */
7019 &fsp1, /* result */
7020 NULL); /* psbuf */
7022 if (!NT_STATUS_IS_OK(status)) {
7023 goto out;
7026 dosattrs = dos_mode(conn, smb_fname_src);
7028 if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
7029 ZERO_STRUCTP(&smb_fname_dst_tmp->st);
7032 /* Open the dst file for writing. */
7033 status = SMB_VFS_CREATE_FILE(
7034 conn, /* conn */
7035 NULL, /* req */
7036 0, /* root_dir_fid */
7037 smb_fname_dst, /* fname */
7038 FILE_GENERIC_WRITE, /* access_mask */
7039 FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
7040 new_create_disposition, /* create_disposition*/
7041 0, /* create_options */
7042 dosattrs, /* file_attributes */
7043 INTERNAL_OPEN_ONLY, /* oplock_request */
7044 0, /* allocation_size */
7045 0, /* private_flags */
7046 NULL, /* sd */
7047 NULL, /* ea_list */
7048 &fsp2, /* result */
7049 NULL); /* psbuf */
7051 if (!NT_STATUS_IS_OK(status)) {
7052 close_file(NULL, fsp1, ERROR_CLOSE);
7053 goto out;
7056 if (ofun & OPENX_FILE_EXISTS_OPEN) {
7057 ret = SMB_VFS_LSEEK(fsp2, 0, SEEK_END);
7058 if (ret == -1) {
7059 DEBUG(0, ("error - vfs lseek returned error %s\n",
7060 strerror(errno)));
7061 status = map_nt_error_from_unix(errno);
7062 close_file(NULL, fsp1, ERROR_CLOSE);
7063 close_file(NULL, fsp2, ERROR_CLOSE);
7064 goto out;
7068 /* Do the actual copy. */
7069 if (smb_fname_src->st.st_ex_size) {
7070 ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
7071 } else {
7072 ret = 0;
7075 close_file(NULL, fsp1, NORMAL_CLOSE);
7077 /* Ensure the modtime is set correctly on the destination file. */
7078 set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
7081 * As we are opening fsp1 read-only we only expect
7082 * an error on close on fsp2 if we are out of space.
7083 * Thus we don't look at the error return from the
7084 * close of fsp1.
7086 status = close_file(NULL, fsp2, NORMAL_CLOSE);
7088 if (!NT_STATUS_IS_OK(status)) {
7089 goto out;
7092 if (ret != (off_t)smb_fname_src->st.st_ex_size) {
7093 status = NT_STATUS_DISK_FULL;
7094 goto out;
7097 status = NT_STATUS_OK;
7099 out:
7100 TALLOC_FREE(smb_fname_dst_tmp);
7101 return status;
7104 /****************************************************************************
7105 Reply to a file copy.
7106 ****************************************************************************/
7108 void reply_copy(struct smb_request *req)
7110 connection_struct *conn = req->conn;
7111 struct smb_filename *smb_fname_src = NULL;
7112 struct smb_filename *smb_fname_dst = NULL;
7113 char *fname_src = NULL;
7114 char *fname_dst = NULL;
7115 char *fname_src_mask = NULL;
7116 char *fname_src_dir = NULL;
7117 const char *p;
7118 int count=0;
7119 int error = ERRnoaccess;
7120 int tid2;
7121 int ofun;
7122 int flags;
7123 bool target_is_directory=False;
7124 bool source_has_wild = False;
7125 bool dest_has_wild = False;
7126 NTSTATUS status;
7127 TALLOC_CTX *ctx = talloc_tos();
7129 START_PROFILE(SMBcopy);
7131 if (req->wct < 3) {
7132 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7133 goto out;
7136 tid2 = SVAL(req->vwv+0, 0);
7137 ofun = SVAL(req->vwv+1, 0);
7138 flags = SVAL(req->vwv+2, 0);
7140 p = (const char *)req->buf;
7141 p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
7142 &status, &source_has_wild);
7143 if (!NT_STATUS_IS_OK(status)) {
7144 reply_nterror(req, status);
7145 goto out;
7147 p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
7148 &status, &dest_has_wild);
7149 if (!NT_STATUS_IS_OK(status)) {
7150 reply_nterror(req, status);
7151 goto out;
7154 DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
7156 if (tid2 != conn->cnum) {
7157 /* can't currently handle inter share copies XXXX */
7158 DEBUG(3,("Rejecting inter-share copy\n"));
7159 reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
7160 goto out;
7163 status = filename_convert(ctx, conn,
7164 req->flags2 & FLAGS2_DFS_PATHNAMES,
7165 fname_src,
7166 UCF_COND_ALLOW_WCARD_LCOMP,
7167 &source_has_wild,
7168 &smb_fname_src);
7169 if (!NT_STATUS_IS_OK(status)) {
7170 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7171 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7172 ERRSRV, ERRbadpath);
7173 goto out;
7175 reply_nterror(req, status);
7176 goto out;
7179 status = filename_convert(ctx, conn,
7180 req->flags2 & FLAGS2_DFS_PATHNAMES,
7181 fname_dst,
7182 UCF_COND_ALLOW_WCARD_LCOMP,
7183 &dest_has_wild,
7184 &smb_fname_dst);
7185 if (!NT_STATUS_IS_OK(status)) {
7186 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7187 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7188 ERRSRV, ERRbadpath);
7189 goto out;
7191 reply_nterror(req, status);
7192 goto out;
7195 target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
7197 if ((flags&1) && target_is_directory) {
7198 reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
7199 goto out;
7202 if ((flags&2) && !target_is_directory) {
7203 reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
7204 goto out;
7207 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
7208 /* wants a tree copy! XXXX */
7209 DEBUG(3,("Rejecting tree copy\n"));
7210 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7211 goto out;
7214 /* Split up the directory from the filename/mask. */
7215 status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
7216 &fname_src_dir, &fname_src_mask);
7217 if (!NT_STATUS_IS_OK(status)) {
7218 reply_nterror(req, NT_STATUS_NO_MEMORY);
7219 goto out;
7223 * We should only check the mangled cache
7224 * here if unix_convert failed. This means
7225 * that the path in 'mask' doesn't exist
7226 * on the file system and so we need to look
7227 * for a possible mangle. This patch from
7228 * Tine Smukavec <valentin.smukavec@hermes.si>.
7230 if (!VALID_STAT(smb_fname_src->st) &&
7231 mangle_is_mangled(fname_src_mask, conn->params)) {
7232 char *new_mask = NULL;
7233 mangle_lookup_name_from_8_3(ctx, fname_src_mask,
7234 &new_mask, conn->params);
7236 /* Use demangled name if one was successfully found. */
7237 if (new_mask) {
7238 TALLOC_FREE(fname_src_mask);
7239 fname_src_mask = new_mask;
7243 if (!source_has_wild) {
7246 * Only one file needs to be copied. Append the mask back onto
7247 * the directory.
7249 TALLOC_FREE(smb_fname_src->base_name);
7250 if (ISDOT(fname_src_dir)) {
7251 /* Ensure we use canonical names on open. */
7252 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7253 "%s",
7254 fname_src_mask);
7255 } else {
7256 smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
7257 "%s/%s",
7258 fname_src_dir,
7259 fname_src_mask);
7261 if (!smb_fname_src->base_name) {
7262 reply_nterror(req, NT_STATUS_NO_MEMORY);
7263 goto out;
7266 if (dest_has_wild) {
7267 char *fname_dst_mod = NULL;
7268 if (!resolve_wildcards(smb_fname_dst,
7269 smb_fname_src->base_name,
7270 smb_fname_dst->base_name,
7271 &fname_dst_mod)) {
7272 reply_nterror(req, NT_STATUS_NO_MEMORY);
7273 goto out;
7275 TALLOC_FREE(smb_fname_dst->base_name);
7276 smb_fname_dst->base_name = fname_dst_mod;
7279 status = check_name(conn, smb_fname_src->base_name);
7280 if (!NT_STATUS_IS_OK(status)) {
7281 reply_nterror(req, status);
7282 goto out;
7285 status = check_name(conn, smb_fname_dst->base_name);
7286 if (!NT_STATUS_IS_OK(status)) {
7287 reply_nterror(req, status);
7288 goto out;
7291 status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
7292 ofun, count, target_is_directory);
7294 if(!NT_STATUS_IS_OK(status)) {
7295 reply_nterror(req, status);
7296 goto out;
7297 } else {
7298 count++;
7300 } else {
7301 struct smb_Dir *dir_hnd = NULL;
7302 const char *dname = NULL;
7303 char *talloced = NULL;
7304 long offset = 0;
7307 * There is a wildcard that requires us to actually read the
7308 * src dir and copy each file matching the mask to the dst.
7309 * Right now streams won't be copied, but this could
7310 * presumably be added with a nested loop for reach dir entry.
7312 SMB_ASSERT(!smb_fname_src->stream_name);
7313 SMB_ASSERT(!smb_fname_dst->stream_name);
7315 smb_fname_src->stream_name = NULL;
7316 smb_fname_dst->stream_name = NULL;
7318 if (strequal(fname_src_mask,"????????.???")) {
7319 TALLOC_FREE(fname_src_mask);
7320 fname_src_mask = talloc_strdup(ctx, "*");
7321 if (!fname_src_mask) {
7322 reply_nterror(req, NT_STATUS_NO_MEMORY);
7323 goto out;
7327 status = check_name(conn, fname_src_dir);
7328 if (!NT_STATUS_IS_OK(status)) {
7329 reply_nterror(req, status);
7330 goto out;
7333 dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
7334 if (dir_hnd == NULL) {
7335 status = map_nt_error_from_unix(errno);
7336 reply_nterror(req, status);
7337 goto out;
7340 error = ERRbadfile;
7342 /* Iterate over the src dir copying each entry to the dst. */
7343 while ((dname = ReadDirName(dir_hnd, &offset,
7344 &smb_fname_src->st, &talloced))) {
7345 char *destname = NULL;
7347 if (ISDOT(dname) || ISDOTDOT(dname)) {
7348 TALLOC_FREE(talloced);
7349 continue;
7352 if (!is_visible_file(conn, fname_src_dir, dname,
7353 &smb_fname_src->st, false)) {
7354 TALLOC_FREE(talloced);
7355 continue;
7358 if(!mask_match(dname, fname_src_mask,
7359 conn->case_sensitive)) {
7360 TALLOC_FREE(talloced);
7361 continue;
7364 error = ERRnoaccess;
7366 /* Get the src smb_fname struct setup. */
7367 TALLOC_FREE(smb_fname_src->base_name);
7368 if (ISDOT(fname_src_dir)) {
7369 /* Ensure we use canonical names on open. */
7370 smb_fname_src->base_name =
7371 talloc_asprintf(smb_fname_src, "%s",
7372 dname);
7373 } else {
7374 smb_fname_src->base_name =
7375 talloc_asprintf(smb_fname_src, "%s/%s",
7376 fname_src_dir, dname);
7379 if (!smb_fname_src->base_name) {
7380 TALLOC_FREE(dir_hnd);
7381 TALLOC_FREE(talloced);
7382 reply_nterror(req, NT_STATUS_NO_MEMORY);
7383 goto out;
7386 if (!resolve_wildcards(ctx, smb_fname_src->base_name,
7387 smb_fname_dst->base_name,
7388 &destname)) {
7389 TALLOC_FREE(talloced);
7390 continue;
7392 if (!destname) {
7393 TALLOC_FREE(dir_hnd);
7394 TALLOC_FREE(talloced);
7395 reply_nterror(req, NT_STATUS_NO_MEMORY);
7396 goto out;
7399 TALLOC_FREE(smb_fname_dst->base_name);
7400 smb_fname_dst->base_name = destname;
7402 status = check_name(conn, smb_fname_src->base_name);
7403 if (!NT_STATUS_IS_OK(status)) {
7404 TALLOC_FREE(dir_hnd);
7405 TALLOC_FREE(talloced);
7406 reply_nterror(req, status);
7407 goto out;
7410 status = check_name(conn, smb_fname_dst->base_name);
7411 if (!NT_STATUS_IS_OK(status)) {
7412 TALLOC_FREE(dir_hnd);
7413 TALLOC_FREE(talloced);
7414 reply_nterror(req, status);
7415 goto out;
7418 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
7419 smb_fname_src->base_name,
7420 smb_fname_dst->base_name));
7422 status = copy_file(ctx, conn, smb_fname_src,
7423 smb_fname_dst, ofun, count,
7424 target_is_directory);
7425 if (NT_STATUS_IS_OK(status)) {
7426 count++;
7429 TALLOC_FREE(talloced);
7431 TALLOC_FREE(dir_hnd);
7434 if (count == 0) {
7435 reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
7436 goto out;
7439 reply_outbuf(req, 1, 0);
7440 SSVAL(req->outbuf,smb_vwv0,count);
7441 out:
7442 TALLOC_FREE(smb_fname_src);
7443 TALLOC_FREE(smb_fname_dst);
7444 TALLOC_FREE(fname_src);
7445 TALLOC_FREE(fname_dst);
7446 TALLOC_FREE(fname_src_mask);
7447 TALLOC_FREE(fname_src_dir);
7449 END_PROFILE(SMBcopy);
7450 return;
7453 #undef DBGC_CLASS
7454 #define DBGC_CLASS DBGC_LOCKING
7456 /****************************************************************************
7457 Get a lock pid, dealing with large count requests.
7458 ****************************************************************************/
7460 uint64_t get_lock_pid(const uint8_t *data, int data_offset,
7461 bool large_file_format)
7463 if(!large_file_format)
7464 return (uint64_t)SVAL(data,SMB_LPID_OFFSET(data_offset));
7465 else
7466 return (uint64_t)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
7469 /****************************************************************************
7470 Get a lock count, dealing with large count requests.
7471 ****************************************************************************/
7473 uint64_t get_lock_count(const uint8_t *data, int data_offset,
7474 bool large_file_format)
7476 uint64_t count = 0;
7478 if(!large_file_format) {
7479 count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
7480 } else {
7482 #if defined(HAVE_LONGLONG)
7483 count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
7484 ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
7485 #else /* HAVE_LONGLONG */
7488 * NT4.x seems to be broken in that it sends large file (64 bit)
7489 * lockingX calls even if the CAP_LARGE_FILES was *not*
7490 * negotiated. For boxes without large unsigned ints truncate the
7491 * lock count by dropping the top 32 bits.
7494 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
7495 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
7496 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
7497 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
7498 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
7501 count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
7502 #endif /* HAVE_LONGLONG */
7505 return count;
7508 #if !defined(HAVE_LONGLONG)
7509 /****************************************************************************
7510 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
7511 ****************************************************************************/
7513 static uint32 map_lock_offset(uint32 high, uint32 low)
7515 unsigned int i;
7516 uint32 mask = 0;
7517 uint32 highcopy = high;
7520 * Try and find out how many significant bits there are in high.
7523 for(i = 0; highcopy; i++)
7524 highcopy >>= 1;
7527 * We use 31 bits not 32 here as POSIX
7528 * lock offsets may not be negative.
7531 mask = (~0) << (31 - i);
7533 if(low & mask)
7534 return 0; /* Fail. */
7536 high <<= (31 - i);
7538 return (high|low);
7540 #endif /* !defined(HAVE_LONGLONG) */
7542 /****************************************************************************
7543 Get a lock offset, dealing with large offset requests.
7544 ****************************************************************************/
7546 uint64_t get_lock_offset(const uint8_t *data, int data_offset,
7547 bool large_file_format, bool *err)
7549 uint64_t offset = 0;
7551 *err = False;
7553 if(!large_file_format) {
7554 offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
7555 } else {
7557 #if defined(HAVE_LONGLONG)
7558 offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
7559 ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
7560 #else /* HAVE_LONGLONG */
7563 * NT4.x seems to be broken in that it sends large file (64 bit)
7564 * lockingX calls even if the CAP_LARGE_FILES was *not*
7565 * negotiated. For boxes without large unsigned ints mangle the
7566 * lock offset by mapping the top 32 bits onto the lower 32.
7569 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
7570 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7571 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
7572 uint32 new_low = 0;
7574 if((new_low = map_lock_offset(high, low)) == 0) {
7575 *err = True;
7576 return (uint64_t)-1;
7579 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7580 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7581 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7582 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7585 offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7586 #endif /* HAVE_LONGLONG */
7589 return offset;
7592 NTSTATUS smbd_do_locking(struct smb_request *req,
7593 files_struct *fsp,
7594 uint8_t type,
7595 int32_t timeout,
7596 uint16_t num_ulocks,
7597 struct smbd_lock_element *ulocks,
7598 uint16_t num_locks,
7599 struct smbd_lock_element *locks,
7600 bool *async)
7602 connection_struct *conn = req->conn;
7603 int i;
7604 NTSTATUS status = NT_STATUS_OK;
7606 *async = false;
7608 /* Data now points at the beginning of the list
7609 of smb_unlkrng structs */
7610 for(i = 0; i < (int)num_ulocks; i++) {
7611 struct smbd_lock_element *e = &ulocks[i];
7613 DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7614 "pid %u, file %s\n",
7615 (double)e->offset,
7616 (double)e->count,
7617 (unsigned int)e->smblctx,
7618 fsp_str_dbg(fsp)));
7620 if (e->brltype != UNLOCK_LOCK) {
7621 /* this can only happen with SMB2 */
7622 return NT_STATUS_INVALID_PARAMETER;
7625 status = do_unlock(req->sconn->msg_ctx,
7626 fsp,
7627 e->smblctx,
7628 e->count,
7629 e->offset,
7630 WINDOWS_LOCK);
7632 DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7633 nt_errstr(status)));
7635 if (!NT_STATUS_IS_OK(status)) {
7636 return status;
7640 /* Setup the timeout in seconds. */
7642 if (!lp_blocking_locks(SNUM(conn))) {
7643 timeout = 0;
7646 /* Data now points at the beginning of the list
7647 of smb_lkrng structs */
7649 for(i = 0; i < (int)num_locks; i++) {
7650 struct smbd_lock_element *e = &locks[i];
7652 DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for smblctx "
7653 "%llu, file %s timeout = %d\n",
7654 (double)e->offset,
7655 (double)e->count,
7656 (unsigned long long)e->smblctx,
7657 fsp_str_dbg(fsp),
7658 (int)timeout));
7660 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7661 struct blocking_lock_record *blr = NULL;
7663 if (num_locks > 1) {
7665 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7666 * if the lock vector contains one entry. When given mutliple cancel
7667 * requests in a single PDU we expect the server to return an
7668 * error. Windows servers seem to accept the request but only
7669 * cancel the first lock.
7670 * JRA - Do what Windows does (tm) :-).
7673 #if 0
7674 /* MS-CIFS (2.2.4.32.1) behavior. */
7675 return NT_STATUS_DOS(ERRDOS,
7676 ERRcancelviolation);
7677 #else
7678 /* Windows behavior. */
7679 if (i != 0) {
7680 DEBUG(10,("smbd_do_locking: ignoring subsequent "
7681 "cancel request\n"));
7682 continue;
7684 #endif
7687 if (lp_blocking_locks(SNUM(conn))) {
7689 /* Schedule a message to ourselves to
7690 remove the blocking lock record and
7691 return the right error. */
7693 blr = blocking_lock_cancel_smb1(fsp,
7694 e->smblctx,
7695 e->offset,
7696 e->count,
7697 WINDOWS_LOCK,
7698 type,
7699 NT_STATUS_FILE_LOCK_CONFLICT);
7700 if (blr == NULL) {
7701 return NT_STATUS_DOS(
7702 ERRDOS,
7703 ERRcancelviolation);
7706 /* Remove a matching pending lock. */
7707 status = do_lock_cancel(fsp,
7708 e->smblctx,
7709 e->count,
7710 e->offset,
7711 WINDOWS_LOCK,
7712 blr);
7713 } else {
7714 bool blocking_lock = timeout ? true : false;
7715 bool defer_lock = false;
7716 struct byte_range_lock *br_lck;
7717 uint64_t block_smblctx;
7719 br_lck = do_lock(req->sconn->msg_ctx,
7720 fsp,
7721 e->smblctx,
7722 e->count,
7723 e->offset,
7724 e->brltype,
7725 WINDOWS_LOCK,
7726 blocking_lock,
7727 &status,
7728 &block_smblctx,
7729 NULL);
7731 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7732 /* Windows internal resolution for blocking locks seems
7733 to be about 200ms... Don't wait for less than that. JRA. */
7734 if (timeout != -1 && timeout < lp_lock_spin_time()) {
7735 timeout = lp_lock_spin_time();
7737 defer_lock = true;
7740 /* If a lock sent with timeout of zero would fail, and
7741 * this lock has been requested multiple times,
7742 * according to brl_lock_failed() we convert this
7743 * request to a blocking lock with a timeout of between
7744 * 150 - 300 milliseconds.
7746 * If lp_lock_spin_time() has been set to 0, we skip
7747 * this blocking retry and fail immediately.
7749 * Replacement for do_lock_spin(). JRA. */
7751 if (!req->sconn->using_smb2 &&
7752 br_lck && lp_blocking_locks(SNUM(conn)) &&
7753 lp_lock_spin_time() && !blocking_lock &&
7754 NT_STATUS_EQUAL((status),
7755 NT_STATUS_FILE_LOCK_CONFLICT))
7757 defer_lock = true;
7758 timeout = lp_lock_spin_time();
7761 if (br_lck && defer_lock) {
7763 * A blocking lock was requested. Package up
7764 * this smb into a queued request and push it
7765 * onto the blocking lock queue.
7767 if(push_blocking_lock_request(br_lck,
7768 req,
7769 fsp,
7770 timeout,
7772 e->smblctx,
7773 e->brltype,
7774 WINDOWS_LOCK,
7775 e->offset,
7776 e->count,
7777 block_smblctx)) {
7778 TALLOC_FREE(br_lck);
7779 *async = true;
7780 return NT_STATUS_OK;
7784 TALLOC_FREE(br_lck);
7787 if (!NT_STATUS_IS_OK(status)) {
7788 break;
7792 /* If any of the above locks failed, then we must unlock
7793 all of the previous locks (X/Open spec). */
7795 if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7797 if (type & LOCKING_ANDX_CANCEL_LOCK) {
7798 i = -1; /* we want to skip the for loop */
7802 * Ensure we don't do a remove on the lock that just failed,
7803 * as under POSIX rules, if we have a lock already there, we
7804 * will delete it (and we shouldn't) .....
7806 for(i--; i >= 0; i--) {
7807 struct smbd_lock_element *e = &locks[i];
7809 do_unlock(req->sconn->msg_ctx,
7810 fsp,
7811 e->smblctx,
7812 e->count,
7813 e->offset,
7814 WINDOWS_LOCK);
7816 return status;
7819 DEBUG(3, ("smbd_do_locking: %s type=%d num_locks=%d num_ulocks=%d\n",
7820 fsp_fnum_dbg(fsp), (unsigned int)type, num_locks, num_ulocks));
7822 return NT_STATUS_OK;
7825 /****************************************************************************
7826 Reply to a lockingX request.
7827 ****************************************************************************/
7829 void reply_lockingX(struct smb_request *req)
7831 connection_struct *conn = req->conn;
7832 files_struct *fsp;
7833 unsigned char locktype;
7834 unsigned char oplocklevel;
7835 uint16 num_ulocks;
7836 uint16 num_locks;
7837 int32 lock_timeout;
7838 int i;
7839 const uint8_t *data;
7840 bool large_file_format;
7841 bool err;
7842 NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7843 struct smbd_lock_element *ulocks;
7844 struct smbd_lock_element *locks;
7845 bool async = false;
7847 START_PROFILE(SMBlockingX);
7849 if (req->wct < 8) {
7850 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7851 END_PROFILE(SMBlockingX);
7852 return;
7855 fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7856 locktype = CVAL(req->vwv+3, 0);
7857 oplocklevel = CVAL(req->vwv+3, 1);
7858 num_ulocks = SVAL(req->vwv+6, 0);
7859 num_locks = SVAL(req->vwv+7, 0);
7860 lock_timeout = IVAL(req->vwv+4, 0);
7861 large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7863 if (!check_fsp(conn, req, fsp)) {
7864 END_PROFILE(SMBlockingX);
7865 return;
7868 data = req->buf;
7870 if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7871 /* we don't support these - and CANCEL_LOCK makes w2k
7872 and XP reboot so I don't really want to be
7873 compatible! (tridge) */
7874 reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7875 END_PROFILE(SMBlockingX);
7876 return;
7879 /* Check if this is an oplock break on a file
7880 we have granted an oplock on.
7882 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7883 /* Client can insist on breaking to none. */
7884 bool break_to_none = (oplocklevel == 0);
7885 bool result;
7887 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7888 "for %s\n", (unsigned int)oplocklevel,
7889 fsp_fnum_dbg(fsp)));
7892 * Make sure we have granted an exclusive or batch oplock on
7893 * this file.
7896 if (fsp->oplock_type == 0) {
7898 /* The Samba4 nbench simulator doesn't understand
7899 the difference between break to level2 and break
7900 to none from level2 - it sends oplock break
7901 replies in both cases. Don't keep logging an error
7902 message here - just ignore it. JRA. */
7904 DEBUG(5,("reply_lockingX: Error : oplock break from "
7905 "client for %s (oplock=%d) and no "
7906 "oplock granted on this file (%s).\n",
7907 fsp_fnum_dbg(fsp), fsp->oplock_type,
7908 fsp_str_dbg(fsp)));
7910 /* if this is a pure oplock break request then don't
7911 * send a reply */
7912 if (num_locks == 0 && num_ulocks == 0) {
7913 END_PROFILE(SMBlockingX);
7914 return;
7915 } else {
7916 END_PROFILE(SMBlockingX);
7917 reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7918 return;
7922 if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7923 (break_to_none)) {
7924 result = remove_oplock(fsp);
7925 } else {
7926 result = downgrade_oplock(fsp);
7929 if (!result) {
7930 DEBUG(0, ("reply_lockingX: error in removing "
7931 "oplock on file %s\n", fsp_str_dbg(fsp)));
7932 /* Hmmm. Is this panic justified? */
7933 smb_panic("internal tdb error");
7936 reply_to_oplock_break_requests(fsp);
7938 /* if this is a pure oplock break request then don't send a
7939 * reply */
7940 if (num_locks == 0 && num_ulocks == 0) {
7941 /* Sanity check - ensure a pure oplock break is not a
7942 chained request. */
7943 if(CVAL(req->vwv+0, 0) != 0xff)
7944 DEBUG(0,("reply_lockingX: Error : pure oplock "
7945 "break is a chained %d request !\n",
7946 (unsigned int)CVAL(req->vwv+0, 0)));
7947 END_PROFILE(SMBlockingX);
7948 return;
7952 if (req->buflen <
7953 (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7954 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7955 END_PROFILE(SMBlockingX);
7956 return;
7959 ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7960 if (ulocks == NULL) {
7961 reply_nterror(req, NT_STATUS_NO_MEMORY);
7962 END_PROFILE(SMBlockingX);
7963 return;
7966 locks = talloc_array(req, struct smbd_lock_element, num_locks);
7967 if (locks == NULL) {
7968 reply_nterror(req, NT_STATUS_NO_MEMORY);
7969 END_PROFILE(SMBlockingX);
7970 return;
7973 /* Data now points at the beginning of the list
7974 of smb_unlkrng structs */
7975 for(i = 0; i < (int)num_ulocks; i++) {
7976 ulocks[i].smblctx = get_lock_pid(data, i, large_file_format);
7977 ulocks[i].count = get_lock_count(data, i, large_file_format);
7978 ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7979 ulocks[i].brltype = UNLOCK_LOCK;
7982 * There is no error code marked "stupid client bug".... :-).
7984 if(err) {
7985 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7986 END_PROFILE(SMBlockingX);
7987 return;
7991 /* Now do any requested locks */
7992 data += ((large_file_format ? 20 : 10)*num_ulocks);
7994 /* Data now points at the beginning of the list
7995 of smb_lkrng structs */
7997 for(i = 0; i < (int)num_locks; i++) {
7998 locks[i].smblctx = get_lock_pid(data, i, large_file_format);
7999 locks[i].count = get_lock_count(data, i, large_file_format);
8000 locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
8002 if (locktype & LOCKING_ANDX_SHARED_LOCK) {
8003 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8004 locks[i].brltype = PENDING_READ_LOCK;
8005 } else {
8006 locks[i].brltype = READ_LOCK;
8008 } else {
8009 if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
8010 locks[i].brltype = PENDING_WRITE_LOCK;
8011 } else {
8012 locks[i].brltype = WRITE_LOCK;
8017 * There is no error code marked "stupid client bug".... :-).
8019 if(err) {
8020 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8021 END_PROFILE(SMBlockingX);
8022 return;
8026 status = smbd_do_locking(req, fsp,
8027 locktype, lock_timeout,
8028 num_ulocks, ulocks,
8029 num_locks, locks,
8030 &async);
8031 if (!NT_STATUS_IS_OK(status)) {
8032 END_PROFILE(SMBlockingX);
8033 reply_nterror(req, status);
8034 return;
8036 if (async) {
8037 END_PROFILE(SMBlockingX);
8038 return;
8041 reply_outbuf(req, 2, 0);
8042 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
8043 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
8045 DEBUG(3, ("lockingX %s type=%d num_locks=%d num_ulocks=%d\n",
8046 fsp_fnum_dbg(fsp), (unsigned int)locktype, num_locks, num_ulocks));
8048 END_PROFILE(SMBlockingX);
8051 #undef DBGC_CLASS
8052 #define DBGC_CLASS DBGC_ALL
8054 /****************************************************************************
8055 Reply to a SMBreadbmpx (read block multiplex) request.
8056 Always reply with an error, if someone has a platform really needs this,
8057 please contact vl@samba.org
8058 ****************************************************************************/
8060 void reply_readbmpx(struct smb_request *req)
8062 START_PROFILE(SMBreadBmpx);
8063 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8064 END_PROFILE(SMBreadBmpx);
8065 return;
8068 /****************************************************************************
8069 Reply to a SMBreadbs (read block multiplex secondary) request.
8070 Always reply with an error, if someone has a platform really needs this,
8071 please contact vl@samba.org
8072 ****************************************************************************/
8074 void reply_readbs(struct smb_request *req)
8076 START_PROFILE(SMBreadBs);
8077 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8078 END_PROFILE(SMBreadBs);
8079 return;
8082 /****************************************************************************
8083 Reply to a SMBsetattrE.
8084 ****************************************************************************/
8086 void reply_setattrE(struct smb_request *req)
8088 connection_struct *conn = req->conn;
8089 struct smb_file_time ft;
8090 files_struct *fsp;
8091 NTSTATUS status;
8093 START_PROFILE(SMBsetattrE);
8094 ZERO_STRUCT(ft);
8096 if (req->wct < 7) {
8097 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8098 goto out;
8101 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8103 if(!fsp || (fsp->conn != conn)) {
8104 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8105 goto out;
8109 * Convert the DOS times into unix times.
8112 ft.atime = convert_time_t_to_timespec(
8113 srv_make_unix_date2(req->vwv+3));
8114 ft.mtime = convert_time_t_to_timespec(
8115 srv_make_unix_date2(req->vwv+5));
8116 ft.create_time = convert_time_t_to_timespec(
8117 srv_make_unix_date2(req->vwv+1));
8119 reply_outbuf(req, 0, 0);
8122 * Patch from Ray Frush <frush@engr.colostate.edu>
8123 * Sometimes times are sent as zero - ignore them.
8126 /* Ensure we have a valid stat struct for the source. */
8127 status = vfs_stat_fsp(fsp);
8128 if (!NT_STATUS_IS_OK(status)) {
8129 reply_nterror(req, status);
8130 goto out;
8133 if (!(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
8134 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8135 goto out;
8138 status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
8139 if (!NT_STATUS_IS_OK(status)) {
8140 reply_nterror(req, status);
8141 goto out;
8144 DEBUG( 3, ( "reply_setattrE %s actime=%u modtime=%u "
8145 " createtime=%u\n",
8146 fsp_fnum_dbg(fsp),
8147 (unsigned int)ft.atime.tv_sec,
8148 (unsigned int)ft.mtime.tv_sec,
8149 (unsigned int)ft.create_time.tv_sec
8151 out:
8152 END_PROFILE(SMBsetattrE);
8153 return;
8157 /* Back from the dead for OS/2..... JRA. */
8159 /****************************************************************************
8160 Reply to a SMBwritebmpx (write block multiplex primary) request.
8161 Always reply with an error, if someone has a platform really needs this,
8162 please contact vl@samba.org
8163 ****************************************************************************/
8165 void reply_writebmpx(struct smb_request *req)
8167 START_PROFILE(SMBwriteBmpx);
8168 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8169 END_PROFILE(SMBwriteBmpx);
8170 return;
8173 /****************************************************************************
8174 Reply to a SMBwritebs (write block multiplex secondary) request.
8175 Always reply with an error, if someone has a platform really needs this,
8176 please contact vl@samba.org
8177 ****************************************************************************/
8179 void reply_writebs(struct smb_request *req)
8181 START_PROFILE(SMBwriteBs);
8182 reply_force_doserror(req, ERRSRV, ERRuseSTD);
8183 END_PROFILE(SMBwriteBs);
8184 return;
8187 /****************************************************************************
8188 Reply to a SMBgetattrE.
8189 ****************************************************************************/
8191 void reply_getattrE(struct smb_request *req)
8193 connection_struct *conn = req->conn;
8194 int mode;
8195 files_struct *fsp;
8196 struct timespec create_ts;
8198 START_PROFILE(SMBgetattrE);
8200 if (req->wct < 1) {
8201 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8202 END_PROFILE(SMBgetattrE);
8203 return;
8206 fsp = file_fsp(req, SVAL(req->vwv+0, 0));
8208 if(!fsp || (fsp->conn != conn)) {
8209 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8210 END_PROFILE(SMBgetattrE);
8211 return;
8214 /* Do an fstat on this file */
8215 if(fsp_stat(fsp)) {
8216 reply_nterror(req, map_nt_error_from_unix(errno));
8217 END_PROFILE(SMBgetattrE);
8218 return;
8221 mode = dos_mode(conn, fsp->fsp_name);
8224 * Convert the times into dos times. Set create
8225 * date to be last modify date as UNIX doesn't save
8226 * this.
8229 reply_outbuf(req, 11, 0);
8231 create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
8232 srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
8233 srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
8234 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
8235 /* Should we check pending modtime here ? JRA */
8236 srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
8237 convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
8239 if (mode & FILE_ATTRIBUTE_DIRECTORY) {
8240 SIVAL(req->outbuf, smb_vwv6, 0);
8241 SIVAL(req->outbuf, smb_vwv8, 0);
8242 } else {
8243 uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
8244 SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
8245 SIVAL(req->outbuf, smb_vwv8, allocation_size);
8247 SSVAL(req->outbuf,smb_vwv10, mode);
8249 DEBUG( 3, ( "reply_getattrE %s\n", fsp_fnum_dbg(fsp)));
8251 END_PROFILE(SMBgetattrE);
8252 return;