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
8
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.
13
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.
18
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/>.
21*/
22/*
23   This file handles most of the reply_ calls that the server
24   makes to handle specific protocols
25*/
26
27#include "includes.h"
28#include "smbd/globals.h"
29
30/****************************************************************************
31 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
32 path or anything including wildcards.
33 We're assuming here that '/' is not the second byte in any multibyte char
34 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
35 set.
36****************************************************************************/
37
38/* Custom version for processing POSIX paths. */
39#define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
40
41static NTSTATUS check_path_syntax_internal(char *path,
42					   bool posix_path,
43					   bool *p_last_component_contains_wcard)
44{
45	char *d = path;
46	const char *s = path;
47	NTSTATUS ret = NT_STATUS_OK;
48	bool start_of_name_component = True;
49	bool stream_started = false;
50
51	*p_last_component_contains_wcard = False;
52
53	while (*s) {
54		if (stream_started) {
55			switch (*s) {
56			case '/':
57			case '\\':
58				return NT_STATUS_OBJECT_NAME_INVALID;
59			case ':':
60				if (s[1] == '\0') {
61					return NT_STATUS_OBJECT_NAME_INVALID;
62				}
63				if (strchr_m(&s[1], ':')) {
64					return NT_STATUS_OBJECT_NAME_INVALID;
65				}
66				break;
67			}
68		}
69
70		if ((*s == ':') && !posix_path && !stream_started) {
71			if (*p_last_component_contains_wcard) {
72				return NT_STATUS_OBJECT_NAME_INVALID;
73			}
74			/* Stream names allow more characters than file names.
75			   We're overloading posix_path here to allow a wider
76			   range of characters. If stream_started is true this
77			   is still a Windows path even if posix_path is true.
78			   JRA.
79			*/
80			stream_started = true;
81			start_of_name_component = false;
82			posix_path = true;
83
84			if (s[1] == '\0') {
85				return NT_STATUS_OBJECT_NAME_INVALID;
86			}
87		}
88
89		if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
90			/*
91			 * Safe to assume is not the second part of a mb char
92			 * as this is handled below.
93			 */
94			/* Eat multiple '/' or '\\' */
95			while (IS_PATH_SEP(*s,posix_path)) {
96				s++;
97			}
98			if ((d != path) && (*s != '\0')) {
99				/* We only care about non-leading or trailing '/' or '\\' */
100				*d++ = '/';
101			}
102
103			start_of_name_component = True;
104			/* New component. */
105			*p_last_component_contains_wcard = False;
106			continue;
107		}
108
109		if (start_of_name_component) {
110			if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
111				/* Uh oh - "/../" or "\\..\\"  or "/..\0" or "\\..\0" ! */
112
113				/*
114				 * No mb char starts with '.' so we're safe checking the directory separator here.
115				 */
116
117				/* If  we just added a '/' - delete it */
118				if ((d > path) && (*(d-1) == '/')) {
119					*(d-1) = '\0';
120					d--;
121				}
122
123				/* Are we at the start ? Can't go back further if so. */
124				if (d <= path) {
125					ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
126					break;
127				}
128				/* Go back one level... */
129				/* We know this is safe as '/' cannot be part of a mb sequence. */
130				/* NOTE - if this assumption is invalid we are not in good shape... */
131				/* Decrement d first as d points to the *next* char to write into. */
132				for (d--; d > path; d--) {
133					if (*d == '/')
134						break;
135				}
136				s += 2; /* Else go past the .. */
137				/* We're still at the start of a name component, just the previous one. */
138				continue;
139
140			} else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
141				if (posix_path) {
142					/* Eat the '.' */
143					s++;
144					continue;
145				}
146			}
147
148		}
149
150		if (!(*s & 0x80)) {
151			if (!posix_path) {
152				if (*s <= 0x1f || *s == '|') {
153					return NT_STATUS_OBJECT_NAME_INVALID;
154				}
155				switch (*s) {
156					case '*':
157					case '?':
158					case '<':
159					case '>':
160					case '"':
161						*p_last_component_contains_wcard = True;
162						break;
163					default:
164						break;
165				}
166			}
167			*d++ = *s++;
168		} else {
169			size_t siz;
170			/* Get the size of the next MB character. */
171			next_codepoint(s,&siz);
172			switch(siz) {
173				case 5:
174					*d++ = *s++;
175					/*fall through*/
176				case 4:
177					*d++ = *s++;
178					/*fall through*/
179				case 3:
180					*d++ = *s++;
181					/*fall through*/
182				case 2:
183					*d++ = *s++;
184					/*fall through*/
185				case 1:
186					*d++ = *s++;
187					break;
188				default:
189					DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
190					*d = '\0';
191					return NT_STATUS_INVALID_PARAMETER;
192			}
193		}
194		start_of_name_component = False;
195	}
196
197	*d = '\0';
198
199	return ret;
200}
201
202/****************************************************************************
203 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
204 No wildcards allowed.
205****************************************************************************/
206
207NTSTATUS check_path_syntax(char *path)
208{
209	bool ignore;
210	return check_path_syntax_internal(path, False, &ignore);
211}
212
213/****************************************************************************
214 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
215 Wildcards allowed - p_contains_wcard returns true if the last component contained
216 a wildcard.
217****************************************************************************/
218
219NTSTATUS check_path_syntax_wcard(char *path, bool *p_contains_wcard)
220{
221	return check_path_syntax_internal(path, False, p_contains_wcard);
222}
223
224/****************************************************************************
225 Check the path for a POSIX client.
226 We're assuming here that '/' is not the second byte in any multibyte char
227 set (a safe assumption).
228****************************************************************************/
229
230NTSTATUS check_path_syntax_posix(char *path)
231{
232	bool ignore;
233	return check_path_syntax_internal(path, True, &ignore);
234}
235
236/****************************************************************************
237 Pull a string and check the path allowing a wilcard - provide for error return.
238****************************************************************************/
239
240size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
241			const char *base_ptr,
242			uint16 smb_flags2,
243			char **pp_dest,
244			const char *src,
245			size_t src_len,
246			int flags,
247			NTSTATUS *err,
248			bool *contains_wcard)
249{
250	size_t ret;
251
252	*pp_dest = NULL;
253
254	ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
255				 src_len, flags);
256
257	if (!*pp_dest) {
258		*err = NT_STATUS_INVALID_PARAMETER;
259		return ret;
260	}
261
262	*contains_wcard = False;
263
264	if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
265		/*
266		 * For a DFS path the function parse_dfs_path()
267		 * will do the path processing, just make a copy.
268		 */
269		*err = NT_STATUS_OK;
270		return ret;
271	}
272
273	if (lp_posix_pathnames()) {
274		*err = check_path_syntax_posix(*pp_dest);
275	} else {
276		*err = check_path_syntax_wcard(*pp_dest, contains_wcard);
277	}
278
279	return ret;
280}
281
282/****************************************************************************
283 Pull a string and check the path - provide for error return.
284****************************************************************************/
285
286size_t srvstr_get_path(TALLOC_CTX *ctx,
287			const char *base_ptr,
288			uint16 smb_flags2,
289			char **pp_dest,
290			const char *src,
291			size_t src_len,
292			int flags,
293			NTSTATUS *err)
294{
295	bool ignore;
296	return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
297				     src_len, flags, err, &ignore);
298}
299
300size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
301				 char **pp_dest, const char *src, int flags,
302				 NTSTATUS *err, bool *contains_wcard)
303{
304	return srvstr_get_path_wcard(mem_ctx, (char *)req->inbuf, req->flags2,
305				     pp_dest, src, smbreq_bufrem(req, src),
306				     flags, err, contains_wcard);
307}
308
309size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
310			   char **pp_dest, const char *src, int flags,
311			   NTSTATUS *err)
312{
313	bool ignore;
314	return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
315					 flags, err, &ignore);
316}
317
318/****************************************************************************
319 Check if we have a correct fsp pointing to a file. Basic check for open fsp.
320****************************************************************************/
321
322bool check_fsp_open(connection_struct *conn, struct smb_request *req,
323		    files_struct *fsp)
324{
325	if (!(fsp) || !(conn)) {
326		reply_nterror(req, NT_STATUS_INVALID_HANDLE);
327		return False;
328	}
329	if (((conn) != (fsp)->conn) || req->vuid != (fsp)->vuid) {
330		reply_nterror(req, NT_STATUS_INVALID_HANDLE);
331		return False;
332	}
333	return True;
334}
335
336/****************************************************************************
337 Check if we have a correct fsp pointing to a file.
338****************************************************************************/
339
340bool check_fsp(connection_struct *conn, struct smb_request *req,
341	       files_struct *fsp)
342{
343	if (!check_fsp_open(conn, req, fsp)) {
344		return False;
345	}
346	if ((fsp)->is_directory) {
347		reply_nterror(req, NT_STATUS_INVALID_DEVICE_REQUEST);
348		return False;
349	}
350	if ((fsp)->fh->fd == -1) {
351		reply_nterror(req, NT_STATUS_ACCESS_DENIED);
352		return False;
353	}
354	(fsp)->num_smb_operations++;
355	return True;
356}
357
358/****************************************************************************
359 Check if we have a correct fsp pointing to a quota fake file. Replacement for
360 the CHECK_NTQUOTA_HANDLE_OK macro.
361****************************************************************************/
362
363bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
364			      files_struct *fsp)
365{
366	if (!check_fsp_open(conn, req, fsp)) {
367		return false;
368	}
369
370	if (fsp->is_directory) {
371		return false;
372	}
373
374	if (fsp->fake_file_handle == NULL) {
375		return false;
376	}
377
378	if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
379		return false;
380	}
381
382	if (fsp->fake_file_handle->private_data == NULL) {
383		return false;
384	}
385
386	return true;
387}
388
389/****************************************************************************
390 Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro
391****************************************************************************/
392
393bool fsp_belongs_conn(connection_struct *conn, struct smb_request *req,
394		      files_struct *fsp)
395{
396	if ((fsp) && (conn) && ((conn)==(fsp)->conn)
397	    && (req->vuid == (fsp)->vuid)) {
398		return True;
399	}
400
401	reply_nterror(req, NT_STATUS_INVALID_HANDLE);
402	return False;
403}
404
405static bool netbios_session_retarget(const char *name, int name_type)
406{
407	char *trim_name;
408	char *trim_name_type;
409	const char *retarget_parm;
410	char *retarget;
411	char *p;
412	int retarget_type = 0x20;
413	int retarget_port = 139;
414	struct sockaddr_storage retarget_addr;
415	struct sockaddr_in *in_addr;
416	bool ret = false;
417	uint8_t outbuf[10];
418
419	if (get_socket_port(smbd_server_fd()) != 139) {
420		return false;
421	}
422
423	trim_name = talloc_strdup(talloc_tos(), name);
424	if (trim_name == NULL) {
425		goto fail;
426	}
427	trim_char(trim_name, ' ', ' ');
428
429	trim_name_type = talloc_asprintf(trim_name, "%s#%2.2x", trim_name,
430					 name_type);
431	if (trim_name_type == NULL) {
432		goto fail;
433	}
434
435	retarget_parm = lp_parm_const_string(-1, "netbios retarget",
436					     trim_name_type, NULL);
437	if (retarget_parm == NULL) {
438		retarget_parm = lp_parm_const_string(-1, "netbios retarget",
439						     trim_name, NULL);
440	}
441	if (retarget_parm == NULL) {
442		goto fail;
443	}
444
445	retarget = talloc_strdup(trim_name, retarget_parm);
446	if (retarget == NULL) {
447		goto fail;
448	}
449
450	DEBUG(10, ("retargeting %s to %s\n", trim_name_type, retarget));
451
452	p = strchr(retarget, ':');
453	if (p != NULL) {
454		*p++ = '\0';
455		retarget_port = atoi(p);
456	}
457
458	p = strchr_m(retarget, '#');
459	if (p != NULL) {
460		*p++ = '\0';
461		sscanf(p, "%x", &retarget_type);
462	}
463
464	ret = resolve_name(retarget, &retarget_addr, retarget_type, false);
465	if (!ret) {
466		DEBUG(10, ("could not resolve %s\n", retarget));
467		goto fail;
468	}
469
470	if (retarget_addr.ss_family != AF_INET) {
471		DEBUG(10, ("Retarget target not an IPv4 addr\n"));
472		goto fail;
473	}
474
475	in_addr = (struct sockaddr_in *)(void *)&retarget_addr;
476
477	_smb_setlen(outbuf, 6);
478	SCVAL(outbuf, 0, 0x84);
479	*(uint32_t *)(outbuf+4) = in_addr->sin_addr.s_addr;
480	*(uint16_t *)(outbuf+8) = htons(retarget_port);
481
482	if (!srv_send_smb(smbd_server_fd(), (char *)outbuf, false, 0, false,
483			  NULL)) {
484		exit_server_cleanly("netbios_session_regarget: srv_send_smb "
485				    "failed.");
486	}
487
488	ret = true;
489 fail:
490	TALLOC_FREE(trim_name);
491	return ret;
492}
493
494/****************************************************************************
495 Reply to a (netbios-level) special message.
496****************************************************************************/
497
498void reply_special(char *inbuf, size_t inbuf_size)
499{
500	int msg_type = CVAL(inbuf,0);
501	int msg_flags = CVAL(inbuf,1);
502	struct smbd_server_connection *sconn = smbd_server_conn;
503	/*
504	 * We only really use 4 bytes of the outbuf, but for the smb_setlen
505	 * calculation & friends (srv_send_smb uses that) we need the full smb
506	 * header.
507	 */
508	char outbuf[smb_size];
509
510	memset(outbuf, '\0', sizeof(outbuf));
511
512	smb_setlen(outbuf,0);
513
514	switch (msg_type) {
515	case 0x81: /* session request */
516	{
517		/* inbuf_size is guarenteed to be at least 4. */
518		fstring name1,name2;
519		int name_type1, name_type2;
520		int name_len1, name_len2;
521
522		*name1 = *name2 = 0;
523
524		if (sconn->nbt.got_session) {
525			exit_server_cleanly("multiple session request not permitted");
526		}
527
528		SCVAL(outbuf,0,0x82);
529		SCVAL(outbuf,3,0);
530
531		/* inbuf_size is guaranteed to be at least 4. */
532		name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4);
533		if (name_len1 <= 0 || name_len1 > inbuf_size - 4) {
534			DEBUG(0,("Invalid name length in session request\n"));
535			return;
536		}
537		name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1);
538		if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) {
539			DEBUG(0,("Invalid name length in session request\n"));
540			return;
541		}
542
543		name_type1 = name_extract((unsigned char *)inbuf,
544				inbuf_size,(unsigned int)4,name1);
545		name_type2 = name_extract((unsigned char *)inbuf,
546				inbuf_size,(unsigned int)(4 + name_len1),name2);
547
548		if (name_type1 == -1 || name_type2 == -1) {
549			DEBUG(0,("Invalid name type in session request\n"));
550			return;
551		}
552
553		DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n",
554			 name1, name_type1, name2, name_type2));
555
556		if (netbios_session_retarget(name1, name_type1)) {
557			exit_server_cleanly("retargeted client");
558		}
559
560		set_local_machine_name(name1, True);
561		set_remote_machine_name(name2, True);
562
563		DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
564			 get_local_machine_name(), get_remote_machine_name(),
565			 name_type2));
566
567		if (name_type2 == 'R') {
568			/* We are being asked for a pathworks session ---
569			   no thanks! */
570			SCVAL(outbuf, 0,0x83);
571			break;
572		}
573
574		/* only add the client's machine name to the list
575		   of possibly valid usernames if we are operating
576		   in share mode security */
577		if (lp_security() == SEC_SHARE) {
578			add_session_user(sconn, get_remote_machine_name());
579		}
580
581		reload_services(True);
582		reopen_logs();
583
584		sconn->nbt.got_session = true;
585		break;
586	}
587
588	case 0x89: /* session keepalive request
589		      (some old clients produce this?) */
590		SCVAL(outbuf,0,SMBkeepalive);
591		SCVAL(outbuf,3,0);
592		break;
593
594	case 0x82: /* positive session response */
595	case 0x83: /* negative session response */
596	case 0x84: /* retarget session response */
597		DEBUG(0,("Unexpected session response\n"));
598		break;
599
600	case SMBkeepalive: /* session keepalive */
601	default:
602		return;
603	}
604
605	DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
606		    msg_type, msg_flags));
607
608	srv_send_smb(smbd_server_fd(), outbuf, false, 0, false, NULL);
609	return;
610}
611
612/****************************************************************************
613 Reply to a tcon.
614 conn POINTER CAN BE NULL HERE !
615****************************************************************************/
616
617void reply_tcon(struct smb_request *req)
618{
619	connection_struct *conn = req->conn;
620	const char *service;
621	char *service_buf = NULL;
622	char *password = NULL;
623	char *dev = NULL;
624	int pwlen=0;
625	NTSTATUS nt_status;
626	const char *p;
627	DATA_BLOB password_blob;
628	TALLOC_CTX *ctx = talloc_tos();
629	struct smbd_server_connection *sconn = smbd_server_conn;
630
631	START_PROFILE(SMBtcon);
632
633	if (req->buflen < 4) {
634		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
635		END_PROFILE(SMBtcon);
636		return;
637	}
638
639	p = (const char *)req->buf + 1;
640	p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
641	p += 1;
642	pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
643	p += pwlen+1;
644	p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
645	p += 1;
646
647	if (service_buf == NULL || password == NULL || dev == NULL) {
648		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
649		END_PROFILE(SMBtcon);
650		return;
651	}
652	p = strrchr_m(service_buf,'\\');
653	if (p) {
654		service = p+1;
655	} else {
656		service = service_buf;
657	}
658
659	password_blob = data_blob(password, pwlen+1);
660
661	conn = make_connection(sconn,service,password_blob,dev,
662			       req->vuid,&nt_status);
663	req->conn = conn;
664
665	data_blob_clear_free(&password_blob);
666
667	if (!conn) {
668		reply_nterror(req, nt_status);
669		END_PROFILE(SMBtcon);
670		return;
671	}
672
673	reply_outbuf(req, 2, 0);
674	SSVAL(req->outbuf,smb_vwv0,sconn->smb1.negprot.max_recv);
675	SSVAL(req->outbuf,smb_vwv1,conn->cnum);
676	SSVAL(req->outbuf,smb_tid,conn->cnum);
677
678	DEBUG(3,("tcon service=%s cnum=%d\n",
679		 service, conn->cnum));
680
681	END_PROFILE(SMBtcon);
682	return;
683}
684
685/****************************************************************************
686 Reply to a tcon and X.
687 conn POINTER CAN BE NULL HERE !
688****************************************************************************/
689
690void reply_tcon_and_X(struct smb_request *req)
691{
692	connection_struct *conn = req->conn;
693	const char *service = NULL;
694	DATA_BLOB password;
695	TALLOC_CTX *ctx = talloc_tos();
696	/* what the cleint thinks the device is */
697	char *client_devicetype = NULL;
698	/* what the server tells the client the share represents */
699	const char *server_devicetype;
700	NTSTATUS nt_status;
701	int passlen;
702	char *path = NULL;
703	const char *p, *q;
704	uint16 tcon_flags;
705	struct smbd_server_connection *sconn = smbd_server_conn;
706
707	START_PROFILE(SMBtconX);
708
709	if (req->wct < 4) {
710		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
711		END_PROFILE(SMBtconX);
712		return;
713	}
714
715	passlen = SVAL(req->vwv+3, 0);
716	tcon_flags = SVAL(req->vwv+2, 0);
717
718	/* we might have to close an old one */
719	if ((tcon_flags & 0x1) && conn) {
720		close_cnum(conn,req->vuid);
721		req->conn = NULL;
722		conn = NULL;
723	}
724
725	if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
726		reply_force_doserror(req, ERRDOS, ERRbuftoosmall);
727		END_PROFILE(SMBtconX);
728		return;
729	}
730
731	if (sconn->smb1.negprot.encrypted_passwords) {
732		password = data_blob_talloc(talloc_tos(), req->buf, passlen);
733		if (lp_security() == SEC_SHARE) {
734			/*
735			 * Security = share always has a pad byte
736			 * after the password.
737			 */
738			p = (const char *)req->buf + passlen + 1;
739		} else {
740			p = (const char *)req->buf + passlen;
741		}
742	} else {
743		password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
744		/* Ensure correct termination */
745		password.data[passlen]=0;
746		p = (const char *)req->buf + passlen + 1;
747	}
748
749	p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
750
751	if (path == NULL) {
752		data_blob_clear_free(&password);
753		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
754		END_PROFILE(SMBtconX);
755		return;
756	}
757
758	/*
759	 * the service name can be either: \\server\share
760	 * or share directly like on the DELL PowerVault 705
761	 */
762	if (*path=='\\') {
763		q = strchr_m(path+2,'\\');
764		if (!q) {
765			data_blob_clear_free(&password);
766			reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME);
767			END_PROFILE(SMBtconX);
768			return;
769		}
770		service = q+1;
771	} else {
772		service = path;
773	}
774
775	p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
776				&client_devicetype, p,
777				MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
778
779	if (client_devicetype == NULL) {
780		data_blob_clear_free(&password);
781		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
782		END_PROFILE(SMBtconX);
783		return;
784	}
785
786	DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
787
788	conn = make_connection(sconn, service, password, client_devicetype,
789			       req->vuid, &nt_status);
790	req->conn =conn;
791
792	data_blob_clear_free(&password);
793
794	if (!conn) {
795		reply_nterror(req, nt_status);
796		END_PROFILE(SMBtconX);
797		return;
798	}
799
800	if ( IS_IPC(conn) )
801		server_devicetype = "IPC";
802	else if ( IS_PRINT(conn) )
803		server_devicetype = "LPT1:";
804	else
805		server_devicetype = "A:";
806
807	if (get_Protocol() < PROTOCOL_NT1) {
808		reply_outbuf(req, 2, 0);
809		if (message_push_string(&req->outbuf, server_devicetype,
810					STR_TERMINATE|STR_ASCII) == -1) {
811			reply_nterror(req, NT_STATUS_NO_MEMORY);
812			END_PROFILE(SMBtconX);
813			return;
814		}
815	} else {
816		/* NT sets the fstype of IPC$ to the null string */
817		const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
818
819		if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
820			/* Return permissions. */
821			uint32 perm1 = 0;
822			uint32 perm2 = 0;
823
824			reply_outbuf(req, 7, 0);
825
826			if (IS_IPC(conn)) {
827				perm1 = FILE_ALL_ACCESS;
828				perm2 = FILE_ALL_ACCESS;
829			} else {
830				perm1 = CAN_WRITE(conn) ?
831						SHARE_ALL_ACCESS :
832						SHARE_READ_ONLY;
833			}
834
835			SIVAL(req->outbuf, smb_vwv3, perm1);
836			SIVAL(req->outbuf, smb_vwv5, perm2);
837		} else {
838			reply_outbuf(req, 3, 0);
839		}
840
841		if ((message_push_string(&req->outbuf, server_devicetype,
842					 STR_TERMINATE|STR_ASCII) == -1)
843		    || (message_push_string(&req->outbuf, fstype,
844					    STR_TERMINATE) == -1)) {
845			reply_nterror(req, NT_STATUS_NO_MEMORY);
846			END_PROFILE(SMBtconX);
847			return;
848		}
849
850		/* what does setting this bit do? It is set by NT4 and
851		   may affect the ability to autorun mounted cdroms */
852		SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
853		      (lp_csc_policy(SNUM(conn)) << 2));
854
855		if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
856			DEBUG(2,("Serving %s as a Dfs root\n",
857				 lp_servicename(SNUM(conn)) ));
858			SSVAL(req->outbuf, smb_vwv2,
859			      SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
860		}
861	}
862
863
864	DEBUG(3,("tconX service=%s \n",
865		 service));
866
867	/* set the incoming and outgoing tid to the just created one */
868	SSVAL(req->inbuf,smb_tid,conn->cnum);
869	SSVAL(req->outbuf,smb_tid,conn->cnum);
870
871	END_PROFILE(SMBtconX);
872
873	req->tid = conn->cnum;
874	chain_reply(req);
875	return;
876}
877
878/****************************************************************************
879 Reply to an unknown type.
880****************************************************************************/
881
882void reply_unknown_new(struct smb_request *req, uint8 type)
883{
884	DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n",
885		  smb_fn_name(type), type, type));
886	reply_force_doserror(req, ERRSRV, ERRunknownsmb);
887	return;
888}
889
890/****************************************************************************
891 Reply to an ioctl.
892 conn POINTER CAN BE NULL HERE !
893****************************************************************************/
894
895void reply_ioctl(struct smb_request *req)
896{
897	connection_struct *conn = req->conn;
898	uint16 device;
899	uint16 function;
900	uint32 ioctl_code;
901	int replysize;
902	char *p;
903
904	START_PROFILE(SMBioctl);
905
906	if (req->wct < 3) {
907		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
908		END_PROFILE(SMBioctl);
909		return;
910	}
911
912	device     = SVAL(req->vwv+1, 0);
913	function   = SVAL(req->vwv+2, 0);
914	ioctl_code = (device << 16) + function;
915
916	DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
917
918	switch (ioctl_code) {
919	    case IOCTL_QUERY_JOB_INFO:
920		    replysize = 32;
921		    break;
922	    default:
923		    reply_force_doserror(req, ERRSRV, ERRnosupport);
924		    END_PROFILE(SMBioctl);
925		    return;
926	}
927
928	reply_outbuf(req, 8, replysize+1);
929	SSVAL(req->outbuf,smb_vwv1,replysize); /* Total data bytes returned */
930	SSVAL(req->outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
931	SSVAL(req->outbuf,smb_vwv6,52);        /* Offset to data */
932	p = smb_buf(req->outbuf);
933	memset(p, '\0', replysize+1); /* valgrind-safe. */
934	p += 1;          /* Allow for alignment */
935
936	switch (ioctl_code) {
937		case IOCTL_QUERY_JOB_INFO:
938		{
939			files_struct *fsp = file_fsp(
940				req, SVAL(req->vwv+0, 0));
941			if (!fsp) {
942				reply_nterror(req, NT_STATUS_INVALID_HANDLE);
943				END_PROFILE(SMBioctl);
944				return;
945			}
946			SSVAL(p,0,fsp->rap_print_jobid);             /* Job number */
947			srvstr_push((char *)req->outbuf, req->flags2, p+2,
948				    global_myname(), 15,
949				    STR_TERMINATE|STR_ASCII);
950			if (conn) {
951				srvstr_push((char *)req->outbuf, req->flags2,
952					    p+18, lp_servicename(SNUM(conn)),
953					    13, STR_TERMINATE|STR_ASCII);
954			} else {
955				memset(p+18, 0, 13);
956			}
957			break;
958		}
959	}
960
961	END_PROFILE(SMBioctl);
962	return;
963}
964
965/****************************************************************************
966 Strange checkpath NTSTATUS mapping.
967****************************************************************************/
968
969static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
970{
971	/* Strange DOS error code semantics only for checkpath... */
972	if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
973		if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
974			/* We need to map to ERRbadpath */
975			return NT_STATUS_OBJECT_PATH_NOT_FOUND;
976		}
977	}
978	return status;
979}
980
981/****************************************************************************
982 Reply to a checkpath.
983****************************************************************************/
984
985void reply_checkpath(struct smb_request *req)
986{
987	connection_struct *conn = req->conn;
988	struct smb_filename *smb_fname = NULL;
989	char *name = NULL;
990	NTSTATUS status;
991	TALLOC_CTX *ctx = talloc_tos();
992
993	START_PROFILE(SMBcheckpath);
994
995	srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
996			    STR_TERMINATE, &status);
997
998	if (!NT_STATUS_IS_OK(status)) {
999		status = map_checkpath_error(req->flags2, status);
1000		reply_nterror(req, status);
1001		END_PROFILE(SMBcheckpath);
1002		return;
1003	}
1004
1005	DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
1006
1007	status = filename_convert(ctx,
1008				conn,
1009				req->flags2 & FLAGS2_DFS_PATHNAMES,
1010				name,
1011				0,
1012				NULL,
1013				&smb_fname);
1014
1015	if (!NT_STATUS_IS_OK(status)) {
1016		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1017			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1018					ERRSRV, ERRbadpath);
1019			END_PROFILE(SMBcheckpath);
1020			return;
1021		}
1022		goto path_err;
1023	}
1024
1025	if (!VALID_STAT(smb_fname->st) &&
1026	    (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1027		DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",
1028			smb_fname_str_dbg(smb_fname), strerror(errno)));
1029		status = map_nt_error_from_unix(errno);
1030		goto path_err;
1031	}
1032
1033	if (!S_ISDIR(smb_fname->st.st_ex_mode)) {
1034		reply_botherror(req, NT_STATUS_NOT_A_DIRECTORY,
1035				ERRDOS, ERRbadpath);
1036		goto out;
1037	}
1038
1039	reply_outbuf(req, 0, 0);
1040
1041 path_err:
1042	/* We special case this - as when a Windows machine
1043		is parsing a path is steps through the components
1044		one at a time - if a component fails it expects
1045		ERRbadpath, not ERRbadfile.
1046	*/
1047	status = map_checkpath_error(req->flags2, status);
1048	if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1049		/*
1050		 * Windows returns different error codes if
1051		 * the parent directory is valid but not the
1052		 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
1053		 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
1054		 * if the path is invalid.
1055		 */
1056		reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND,
1057				ERRDOS, ERRbadpath);
1058		goto out;
1059	}
1060
1061	reply_nterror(req, status);
1062
1063 out:
1064	TALLOC_FREE(smb_fname);
1065	END_PROFILE(SMBcheckpath);
1066	return;
1067}
1068
1069/****************************************************************************
1070 Reply to a getatr.
1071****************************************************************************/
1072
1073void reply_getatr(struct smb_request *req)
1074{
1075	connection_struct *conn = req->conn;
1076	struct smb_filename *smb_fname = NULL;
1077	char *fname = NULL;
1078	int mode=0;
1079	SMB_OFF_T size=0;
1080	time_t mtime=0;
1081	const char *p;
1082	NTSTATUS status;
1083	TALLOC_CTX *ctx = talloc_tos();
1084	bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1085
1086	START_PROFILE(SMBgetatr);
1087
1088	p = (const char *)req->buf + 1;
1089	p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1090	if (!NT_STATUS_IS_OK(status)) {
1091		reply_nterror(req, status);
1092		goto out;
1093	}
1094
1095	/* dos smetimes asks for a stat of "" - it returns a "hidden directory"
1096		under WfWg - weird! */
1097	if (*fname == '\0') {
1098		mode = aHIDDEN | aDIR;
1099		if (!CAN_WRITE(conn)) {
1100			mode |= aRONLY;
1101		}
1102		size = 0;
1103		mtime = 0;
1104	} else {
1105		status = filename_convert(ctx,
1106				conn,
1107				req->flags2 & FLAGS2_DFS_PATHNAMES,
1108				fname,
1109				0,
1110				NULL,
1111				&smb_fname);
1112		if (!NT_STATUS_IS_OK(status)) {
1113			if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1114				reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1115						ERRSRV, ERRbadpath);
1116				goto out;
1117			}
1118			reply_nterror(req, status);
1119			goto out;
1120		}
1121		if (!VALID_STAT(smb_fname->st) &&
1122		    (SMB_VFS_STAT(conn, smb_fname) != 0)) {
1123			DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",
1124				 smb_fname_str_dbg(smb_fname),
1125				 strerror(errno)));
1126			reply_nterror(req,  map_nt_error_from_unix(errno));
1127			goto out;
1128		}
1129
1130		mode = dos_mode(conn, smb_fname);
1131		size = smb_fname->st.st_ex_size;
1132
1133		if (ask_sharemode) {
1134			struct timespec write_time_ts;
1135			struct file_id fileid;
1136
1137			ZERO_STRUCT(write_time_ts);
1138			fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1139			get_file_infos(fileid, NULL, &write_time_ts);
1140			if (!null_timespec(write_time_ts)) {
1141				update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1142			}
1143		}
1144
1145		mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1146		if (mode & aDIR) {
1147			size = 0;
1148		}
1149	}
1150
1151	reply_outbuf(req, 10, 0);
1152
1153	SSVAL(req->outbuf,smb_vwv0,mode);
1154	if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1155		srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime & ~1);
1156	} else {
1157		srv_put_dos_date3((char *)req->outbuf,smb_vwv1,mtime);
1158	}
1159	SIVAL(req->outbuf,smb_vwv3,(uint32)size);
1160
1161	if (get_Protocol() >= PROTOCOL_NT1) {
1162		SSVAL(req->outbuf, smb_flg2,
1163		      SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
1164	}
1165
1166	DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n",
1167		 smb_fname_str_dbg(smb_fname), mode, (unsigned int)size));
1168
1169 out:
1170	TALLOC_FREE(smb_fname);
1171	TALLOC_FREE(fname);
1172	END_PROFILE(SMBgetatr);
1173	return;
1174}
1175
1176/****************************************************************************
1177 Reply to a setatr.
1178****************************************************************************/
1179
1180void reply_setatr(struct smb_request *req)
1181{
1182	struct smb_file_time ft;
1183	connection_struct *conn = req->conn;
1184	struct smb_filename *smb_fname = NULL;
1185	char *fname = NULL;
1186	int mode;
1187	time_t mtime;
1188	const char *p;
1189	NTSTATUS status;
1190	TALLOC_CTX *ctx = talloc_tos();
1191
1192	START_PROFILE(SMBsetatr);
1193
1194	ZERO_STRUCT(ft);
1195
1196	if (req->wct < 2) {
1197		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1198		goto out;
1199	}
1200
1201	p = (const char *)req->buf + 1;
1202	p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
1203	if (!NT_STATUS_IS_OK(status)) {
1204		reply_nterror(req, status);
1205		goto out;
1206	}
1207
1208	status = filename_convert(ctx,
1209				conn,
1210				req->flags2 & FLAGS2_DFS_PATHNAMES,
1211				fname,
1212				0,
1213				NULL,
1214				&smb_fname);
1215	if (!NT_STATUS_IS_OK(status)) {
1216		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1217			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1218					ERRSRV, ERRbadpath);
1219			goto out;
1220		}
1221		reply_nterror(req, status);
1222		goto out;
1223	}
1224
1225	if (smb_fname->base_name[0] == '.' &&
1226	    smb_fname->base_name[1] == '\0') {
1227		/*
1228		 * Not sure here is the right place to catch this
1229		 * condition. Might be moved to somewhere else later -- vl
1230		 */
1231		reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1232		goto out;
1233	}
1234
1235	mode = SVAL(req->vwv+0, 0);
1236	mtime = srv_make_unix_date3(req->vwv+1);
1237
1238	ft.mtime = convert_time_t_to_timespec(mtime);
1239	status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
1240	if (!NT_STATUS_IS_OK(status)) {
1241		reply_nterror(req, status);
1242		goto out;
1243	}
1244
1245	if (mode != FILE_ATTRIBUTE_NORMAL) {
1246		if (VALID_STAT_OF_DIR(smb_fname->st))
1247			mode |= aDIR;
1248		else
1249			mode &= ~aDIR;
1250
1251		if (file_set_dosmode(conn, smb_fname, mode, NULL,
1252				     false) != 0) {
1253			reply_nterror(req, map_nt_error_from_unix(errno));
1254			goto out;
1255		}
1256	}
1257
1258	reply_outbuf(req, 0, 0);
1259
1260	DEBUG(3, ("setatr name=%s mode=%d\n", smb_fname_str_dbg(smb_fname),
1261		 mode));
1262 out:
1263	TALLOC_FREE(smb_fname);
1264	END_PROFILE(SMBsetatr);
1265	return;
1266}
1267
1268/****************************************************************************
1269 Reply to a dskattr.
1270****************************************************************************/
1271
1272void reply_dskattr(struct smb_request *req)
1273{
1274	connection_struct *conn = req->conn;
1275	uint64_t dfree,dsize,bsize;
1276	START_PROFILE(SMBdskattr);
1277
1278	if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
1279		reply_nterror(req, map_nt_error_from_unix(errno));
1280		END_PROFILE(SMBdskattr);
1281		return;
1282	}
1283
1284	reply_outbuf(req, 5, 0);
1285
1286	if (get_Protocol() <= PROTOCOL_LANMAN2) {
1287		double total_space, free_space;
1288		/* we need to scale this to a number that DOS6 can handle. We
1289		   use floating point so we can handle large drives on systems
1290		   that don't have 64 bit integers
1291
1292		   we end up displaying a maximum of 2G to DOS systems
1293		*/
1294		total_space = dsize * (double)bsize;
1295		free_space = dfree * (double)bsize;
1296
1297		dsize = (uint64_t)((total_space+63*512) / (64*512));
1298		dfree = (uint64_t)((free_space+63*512) / (64*512));
1299
1300		if (dsize > 0xFFFF) dsize = 0xFFFF;
1301		if (dfree > 0xFFFF) dfree = 0xFFFF;
1302
1303		SSVAL(req->outbuf,smb_vwv0,dsize);
1304		SSVAL(req->outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
1305		SSVAL(req->outbuf,smb_vwv2,512); /* and this must be 512 */
1306		SSVAL(req->outbuf,smb_vwv3,dfree);
1307	} else {
1308		SSVAL(req->outbuf,smb_vwv0,dsize);
1309		SSVAL(req->outbuf,smb_vwv1,bsize/512);
1310		SSVAL(req->outbuf,smb_vwv2,512);
1311		SSVAL(req->outbuf,smb_vwv3,dfree);
1312	}
1313
1314	DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
1315
1316	END_PROFILE(SMBdskattr);
1317	return;
1318}
1319
1320/*
1321 * Utility function to split the filename from the directory.
1322 */
1323static NTSTATUS split_fname_dir_mask(TALLOC_CTX *ctx, const char *fname_in,
1324				     char **fname_dir_out,
1325				     char **fname_mask_out)
1326{
1327	const char *p = NULL;
1328	char *fname_dir = NULL;
1329	char *fname_mask = NULL;
1330
1331	p = strrchr_m(fname_in, '/');
1332	if (!p) {
1333		fname_dir = talloc_strdup(ctx, ".");
1334		fname_mask = talloc_strdup(ctx, fname_in);
1335	} else {
1336		fname_dir = talloc_strndup(ctx, fname_in,
1337		    PTR_DIFF(p, fname_in));
1338		fname_mask = talloc_strdup(ctx, p+1);
1339	}
1340
1341	if (!fname_dir || !fname_mask) {
1342		TALLOC_FREE(fname_dir);
1343		TALLOC_FREE(fname_mask);
1344		return NT_STATUS_NO_MEMORY;
1345	}
1346
1347	*fname_dir_out = fname_dir;
1348	*fname_mask_out = fname_mask;
1349	return NT_STATUS_OK;
1350}
1351
1352/****************************************************************************
1353 Reply to a search.
1354 Can be called from SMBsearch, SMBffirst or SMBfunique.
1355****************************************************************************/
1356
1357void reply_search(struct smb_request *req)
1358{
1359	connection_struct *conn = req->conn;
1360	char *path = NULL;
1361	const char *mask = NULL;
1362	char *directory = NULL;
1363	struct smb_filename *smb_fname = NULL;
1364	char *fname = NULL;
1365	SMB_OFF_T size;
1366	uint32 mode;
1367	struct timespec date;
1368	uint32 dirtype;
1369	unsigned int numentries = 0;
1370	unsigned int maxentries = 0;
1371	bool finished = False;
1372	const char *p;
1373	int status_len;
1374	char status[21];
1375	int dptr_num= -1;
1376	bool check_descend = False;
1377	bool expect_close = False;
1378	NTSTATUS nt_status;
1379	bool mask_contains_wcard = False;
1380	bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
1381	TALLOC_CTX *ctx = talloc_tos();
1382	bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1383	struct dptr_struct *dirptr = NULL;
1384	struct smbd_server_connection *sconn = smbd_server_conn;
1385
1386	START_PROFILE(SMBsearch);
1387
1388	if (req->wct < 2) {
1389		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1390		goto out;
1391	}
1392
1393	if (lp_posix_pathnames()) {
1394		reply_unknown_new(req, req->cmd);
1395		goto out;
1396	}
1397
1398	/* If we were called as SMBffirst then we must expect close. */
1399	if(req->cmd == SMBffirst) {
1400		expect_close = True;
1401	}
1402
1403	reply_outbuf(req, 1, 3);
1404	maxentries = SVAL(req->vwv+0, 0);
1405	dirtype = SVAL(req->vwv+1, 0);
1406	p = (const char *)req->buf + 1;
1407	p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1408				       &nt_status, &mask_contains_wcard);
1409	if (!NT_STATUS_IS_OK(nt_status)) {
1410		reply_nterror(req, nt_status);
1411		goto out;
1412	}
1413
1414	p++;
1415	status_len = SVAL(p, 0);
1416	p += 2;
1417
1418	/* dirtype &= ~aDIR; */
1419
1420	if (status_len == 0) {
1421		nt_status = filename_convert(ctx, conn,
1422					     req->flags2 & FLAGS2_DFS_PATHNAMES,
1423					     path,
1424					     UCF_ALWAYS_ALLOW_WCARD_LCOMP,
1425					     &mask_contains_wcard,
1426					     &smb_fname);
1427		if (!NT_STATUS_IS_OK(nt_status)) {
1428			if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1429				reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1430						ERRSRV, ERRbadpath);
1431				goto out;
1432			}
1433			reply_nterror(req, nt_status);
1434			goto out;
1435		}
1436
1437		directory = smb_fname->base_name;
1438
1439		p = strrchr_m(directory,'/');
1440		if ((p != NULL) && (*directory != '/')) {
1441			mask = p + 1;
1442			directory = talloc_strndup(ctx, directory,
1443						   PTR_DIFF(p, directory));
1444		} else {
1445			mask = directory;
1446			directory = talloc_strdup(ctx,".");
1447		}
1448
1449		if (!directory) {
1450			reply_nterror(req, NT_STATUS_NO_MEMORY);
1451			goto out;
1452		}
1453
1454		memset((char *)status,'\0',21);
1455		SCVAL(status,0,(dirtype & 0x1F));
1456
1457		nt_status = dptr_create(conn,
1458					directory,
1459					True,
1460					expect_close,
1461					req->smbpid,
1462					mask,
1463					mask_contains_wcard,
1464					dirtype,
1465					&dirptr);
1466		if (!NT_STATUS_IS_OK(nt_status)) {
1467			reply_nterror(req, nt_status);
1468			goto out;
1469		}
1470		dptr_num = dptr_dnum(dirptr);
1471	} else {
1472		int status_dirtype;
1473		const char *dirpath;
1474
1475		memcpy(status,p,21);
1476		status_dirtype = CVAL(status,0) & 0x1F;
1477		if (status_dirtype != (dirtype & 0x1F)) {
1478			dirtype = status_dirtype;
1479		}
1480
1481		dirptr = dptr_fetch(sconn, status+12,&dptr_num);
1482		if (!dirptr) {
1483			goto SearchEmpty;
1484		}
1485		dirpath = dptr_path(sconn, dptr_num);
1486		directory = talloc_strdup(ctx, dirpath);
1487		if (!directory) {
1488			reply_nterror(req, NT_STATUS_NO_MEMORY);
1489			goto out;
1490		}
1491
1492		mask = dptr_wcard(sconn, dptr_num);
1493		if (!mask) {
1494			goto SearchEmpty;
1495		}
1496		/*
1497		 * For a 'continue' search we have no string. So
1498		 * check from the initial saved string.
1499		 */
1500		mask_contains_wcard = ms_has_wild(mask);
1501		dirtype = dptr_attr(sconn, dptr_num);
1502	}
1503
1504	DEBUG(4,("dptr_num is %d\n",dptr_num));
1505
1506	/* Initialize per SMBsearch/SMBffirst/SMBfunique operation data */
1507	dptr_init_search_op(dirptr);
1508
1509	if ((dirtype&0x1F) == aVOLID) {
1510		char buf[DIR_STRUCT_SIZE];
1511		memcpy(buf,status,21);
1512		if (!make_dir_struct(ctx,buf,"???????????",volume_label(SNUM(conn)),
1513				0,aVOLID,0,!allow_long_path_components)) {
1514			reply_nterror(req, NT_STATUS_NO_MEMORY);
1515			goto out;
1516		}
1517		dptr_fill(sconn, buf+12,dptr_num);
1518		if (dptr_zero(buf+12) && (status_len==0)) {
1519			numentries = 1;
1520		} else {
1521			numentries = 0;
1522		}
1523		if (message_push_blob(&req->outbuf,
1524				      data_blob_const(buf, sizeof(buf)))
1525		    == -1) {
1526			reply_nterror(req, NT_STATUS_NO_MEMORY);
1527			goto out;
1528		}
1529	} else {
1530		unsigned int i;
1531		maxentries = MIN(
1532			maxentries,
1533			((BUFFER_SIZE -
1534			  ((uint8 *)smb_buf(req->outbuf) + 3 - req->outbuf))
1535			 /DIR_STRUCT_SIZE));
1536
1537		DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1538			directory,lp_dontdescend(SNUM(conn))));
1539		if (in_list(directory, lp_dontdescend(SNUM(conn)),True)) {
1540			check_descend = True;
1541		}
1542
1543		for (i=numentries;(i<maxentries) && !finished;i++) {
1544			finished = !get_dir_entry(ctx,
1545						  dirptr,
1546						  mask,
1547						  dirtype,
1548						  &fname,
1549						  &size,
1550						  &mode,
1551						  &date,
1552						  check_descend,
1553						  ask_sharemode);
1554			if (!finished) {
1555				char buf[DIR_STRUCT_SIZE];
1556				memcpy(buf,status,21);
1557				if (!make_dir_struct(ctx,
1558						buf,
1559						mask,
1560						fname,
1561						size,
1562						mode,
1563						convert_timespec_to_time_t(date),
1564						!allow_long_path_components)) {
1565					reply_nterror(req, NT_STATUS_NO_MEMORY);
1566					goto out;
1567				}
1568				if (!dptr_fill(sconn, buf+12,dptr_num)) {
1569					break;
1570				}
1571				if (message_push_blob(&req->outbuf,
1572						      data_blob_const(buf, sizeof(buf)))
1573				    == -1) {
1574					reply_nterror(req, NT_STATUS_NO_MEMORY);
1575					goto out;
1576				}
1577				numentries++;
1578			}
1579		}
1580	}
1581
1582  SearchEmpty:
1583
1584	/* If we were called as SMBffirst with smb_search_id == NULL
1585		and no entries were found then return error and close dirptr
1586		(X/Open spec) */
1587
1588	if (numentries == 0) {
1589		dptr_close(sconn, &dptr_num);
1590	} else if(expect_close && status_len == 0) {
1591		/* Close the dptr - we know it's gone */
1592		dptr_close(sconn, &dptr_num);
1593	}
1594
1595	/* If we were called as SMBfunique, then we can close the dirptr now ! */
1596	if(dptr_num >= 0 && req->cmd == SMBfunique) {
1597		dptr_close(sconn, &dptr_num);
1598	}
1599
1600	if ((numentries == 0) && !mask_contains_wcard) {
1601		reply_botherror(req, STATUS_NO_MORE_FILES, ERRDOS, ERRnofiles);
1602		goto out;
1603	}
1604
1605	SSVAL(req->outbuf,smb_vwv0,numentries);
1606	SSVAL(req->outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1607	SCVAL(smb_buf(req->outbuf),0,5);
1608	SSVAL(smb_buf(req->outbuf),1,numentries*DIR_STRUCT_SIZE);
1609
1610	/* The replies here are never long name. */
1611	SSVAL(req->outbuf, smb_flg2,
1612	      SVAL(req->outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1613	if (!allow_long_path_components) {
1614		SSVAL(req->outbuf, smb_flg2,
1615		      SVAL(req->outbuf, smb_flg2)
1616		      & (~FLAGS2_LONG_PATH_COMPONENTS));
1617	}
1618
1619	/* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1620	SSVAL(req->outbuf, smb_flg2,
1621	      (SVAL(req->outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1622
1623	DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1624		smb_fn_name(req->cmd),
1625		mask,
1626		directory,
1627		dirtype,
1628		numentries,
1629		maxentries ));
1630 out:
1631	TALLOC_FREE(directory);
1632	TALLOC_FREE(smb_fname);
1633	END_PROFILE(SMBsearch);
1634	return;
1635}
1636
1637/****************************************************************************
1638 Reply to a fclose (stop directory search).
1639****************************************************************************/
1640
1641void reply_fclose(struct smb_request *req)
1642{
1643	int status_len;
1644	char status[21];
1645	int dptr_num= -2;
1646	const char *p;
1647	char *path = NULL;
1648	NTSTATUS err;
1649	bool path_contains_wcard = False;
1650	TALLOC_CTX *ctx = talloc_tos();
1651	struct smbd_server_connection *sconn = smbd_server_conn;
1652
1653	START_PROFILE(SMBfclose);
1654
1655	if (lp_posix_pathnames()) {
1656		reply_unknown_new(req, req->cmd);
1657		END_PROFILE(SMBfclose);
1658		return;
1659	}
1660
1661	p = (const char *)req->buf + 1;
1662	p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
1663				       &err, &path_contains_wcard);
1664	if (!NT_STATUS_IS_OK(err)) {
1665		reply_nterror(req, err);
1666		END_PROFILE(SMBfclose);
1667		return;
1668	}
1669	p++;
1670	status_len = SVAL(p,0);
1671	p += 2;
1672
1673	if (status_len == 0) {
1674		reply_force_doserror(req, ERRSRV, ERRsrverror);
1675		END_PROFILE(SMBfclose);
1676		return;
1677	}
1678
1679	memcpy(status,p,21);
1680
1681	if(dptr_fetch(sconn, status+12,&dptr_num)) {
1682		/*  Close the dptr - we know it's gone */
1683		dptr_close(sconn, &dptr_num);
1684	}
1685
1686	reply_outbuf(req, 1, 0);
1687	SSVAL(req->outbuf,smb_vwv0,0);
1688
1689	DEBUG(3,("search close\n"));
1690
1691	END_PROFILE(SMBfclose);
1692	return;
1693}
1694
1695/****************************************************************************
1696 Reply to an open.
1697****************************************************************************/
1698
1699void reply_open(struct smb_request *req)
1700{
1701	connection_struct *conn = req->conn;
1702	struct smb_filename *smb_fname = NULL;
1703	char *fname = NULL;
1704	uint32 fattr=0;
1705	SMB_OFF_T size = 0;
1706	time_t mtime=0;
1707	int info;
1708	files_struct *fsp;
1709	int oplock_request;
1710	int deny_mode;
1711	uint32 dos_attr;
1712	uint32 access_mask;
1713	uint32 share_mode;
1714	uint32 create_disposition;
1715	uint32 create_options = 0;
1716	NTSTATUS status;
1717	bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1718	TALLOC_CTX *ctx = talloc_tos();
1719
1720	START_PROFILE(SMBopen);
1721
1722	if (req->wct < 2) {
1723		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1724		goto out;
1725	}
1726
1727	oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1728	deny_mode = SVAL(req->vwv+0, 0);
1729	dos_attr = SVAL(req->vwv+1, 0);
1730
1731	srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
1732			    STR_TERMINATE, &status);
1733	if (!NT_STATUS_IS_OK(status)) {
1734		reply_nterror(req, status);
1735		goto out;
1736	}
1737
1738	status = filename_convert(ctx,
1739				conn,
1740				req->flags2 & FLAGS2_DFS_PATHNAMES,
1741				fname,
1742				0,
1743				NULL,
1744				&smb_fname);
1745	if (!NT_STATUS_IS_OK(status)) {
1746		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1747			reply_botherror(req,
1748					NT_STATUS_PATH_NOT_COVERED,
1749					ERRSRV, ERRbadpath);
1750			goto out;
1751		}
1752		reply_nterror(req, status);
1753		goto out;
1754	}
1755
1756	if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1757					 OPENX_FILE_EXISTS_OPEN, &access_mask,
1758					 &share_mode, &create_disposition,
1759					 &create_options)) {
1760		reply_force_doserror(req, ERRDOS, ERRbadaccess);
1761		goto out;
1762	}
1763
1764	status = SMB_VFS_CREATE_FILE(
1765		conn,					/* conn */
1766		req,					/* req */
1767		0,					/* root_dir_fid */
1768		smb_fname,				/* fname */
1769		access_mask,				/* access_mask */
1770		share_mode,				/* share_access */
1771		create_disposition,			/* create_disposition*/
1772		create_options,				/* create_options */
1773		dos_attr,				/* file_attributes */
1774		oplock_request,				/* oplock_request */
1775		0,					/* allocation_size */
1776		NULL,					/* sd */
1777		NULL,					/* ea_list */
1778		&fsp,					/* result */
1779		&info);					/* pinfo */
1780
1781	if (!NT_STATUS_IS_OK(status)) {
1782		if (open_was_deferred(req->mid)) {
1783			/* We have re-scheduled this call. */
1784			goto out;
1785		}
1786		reply_openerror(req, status);
1787		goto out;
1788	}
1789
1790	size = smb_fname->st.st_ex_size;
1791	fattr = dos_mode(conn, smb_fname);
1792
1793	/* Deal with other possible opens having a modified
1794	   write time. JRA. */
1795	if (ask_sharemode) {
1796		struct timespec write_time_ts;
1797
1798		ZERO_STRUCT(write_time_ts);
1799		get_file_infos(fsp->file_id, NULL, &write_time_ts);
1800		if (!null_timespec(write_time_ts)) {
1801			update_stat_ex_mtime(&smb_fname->st, write_time_ts);
1802		}
1803	}
1804
1805	mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1806
1807	if (fattr & aDIR) {
1808		DEBUG(3,("attempt to open a directory %s\n",
1809			 fsp_str_dbg(fsp)));
1810		close_file(req, fsp, ERROR_CLOSE);
1811		reply_botherror(req, NT_STATUS_ACCESS_DENIED,
1812			ERRDOS, ERRnoaccess);
1813		goto out;
1814	}
1815
1816	reply_outbuf(req, 7, 0);
1817	SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
1818	SSVAL(req->outbuf,smb_vwv1,fattr);
1819	if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1820		srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime & ~1);
1821	} else {
1822		srv_put_dos_date3((char *)req->outbuf,smb_vwv2,mtime);
1823	}
1824	SIVAL(req->outbuf,smb_vwv4,(uint32)size);
1825	SSVAL(req->outbuf,smb_vwv6,deny_mode);
1826
1827	if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1828		SCVAL(req->outbuf,smb_flg,
1829		      CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1830	}
1831
1832	if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1833		SCVAL(req->outbuf,smb_flg,
1834		      CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1835	}
1836 out:
1837	TALLOC_FREE(smb_fname);
1838	END_PROFILE(SMBopen);
1839	return;
1840}
1841
1842/****************************************************************************
1843 Reply to an open and X.
1844****************************************************************************/
1845
1846void reply_open_and_X(struct smb_request *req)
1847{
1848	connection_struct *conn = req->conn;
1849	struct smb_filename *smb_fname = NULL;
1850	char *fname = NULL;
1851	uint16 open_flags;
1852	int deny_mode;
1853	uint32 smb_attr;
1854	/* Breakout the oplock request bits so we can set the
1855		reply bits separately. */
1856	int ex_oplock_request;
1857	int core_oplock_request;
1858	int oplock_request;
1859#if 0
1860	int smb_sattr = SVAL(req->vwv+4, 0);
1861	uint32 smb_time = make_unix_date3(req->vwv+6);
1862#endif
1863	int smb_ofun;
1864	uint32 fattr=0;
1865	int mtime=0;
1866	int smb_action = 0;
1867	files_struct *fsp;
1868	NTSTATUS status;
1869	uint64_t allocation_size;
1870	ssize_t retval = -1;
1871	uint32 access_mask;
1872	uint32 share_mode;
1873	uint32 create_disposition;
1874	uint32 create_options = 0;
1875	TALLOC_CTX *ctx = talloc_tos();
1876
1877	START_PROFILE(SMBopenX);
1878
1879	if (req->wct < 15) {
1880		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1881		goto out;
1882	}
1883
1884	open_flags = SVAL(req->vwv+2, 0);
1885	deny_mode = SVAL(req->vwv+3, 0);
1886	smb_attr = SVAL(req->vwv+5, 0);
1887	ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
1888	core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
1889	oplock_request = ex_oplock_request | core_oplock_request;
1890	smb_ofun = SVAL(req->vwv+8, 0);
1891	allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
1892
1893	/* If it's an IPC, pass off the pipe handler. */
1894	if (IS_IPC(conn)) {
1895		if (lp_nt_pipe_support()) {
1896			reply_open_pipe_and_X(conn, req);
1897		} else {
1898			reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1899		}
1900		goto out;
1901	}
1902
1903	/* XXXX we need to handle passed times, sattr and flags */
1904	srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
1905			STR_TERMINATE, &status);
1906	if (!NT_STATUS_IS_OK(status)) {
1907		reply_nterror(req, status);
1908		goto out;
1909	}
1910
1911	status = filename_convert(ctx,
1912				conn,
1913				req->flags2 & FLAGS2_DFS_PATHNAMES,
1914				fname,
1915				0,
1916				NULL,
1917				&smb_fname);
1918	if (!NT_STATUS_IS_OK(status)) {
1919		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1920			reply_botherror(req,
1921					NT_STATUS_PATH_NOT_COVERED,
1922					ERRSRV, ERRbadpath);
1923			goto out;
1924		}
1925		reply_nterror(req, status);
1926		goto out;
1927	}
1928
1929	if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1930					 smb_ofun,
1931					 &access_mask, &share_mode,
1932					 &create_disposition,
1933					 &create_options)) {
1934		reply_force_doserror(req, ERRDOS, ERRbadaccess);
1935		goto out;
1936	}
1937
1938	status = SMB_VFS_CREATE_FILE(
1939		conn,					/* conn */
1940		req,					/* req */
1941		0,					/* root_dir_fid */
1942		smb_fname,				/* fname */
1943		access_mask,				/* access_mask */
1944		share_mode,				/* share_access */
1945		create_disposition,			/* create_disposition*/
1946		create_options,				/* create_options */
1947		smb_attr,				/* file_attributes */
1948		oplock_request,				/* oplock_request */
1949		0,					/* allocation_size */
1950		NULL,					/* sd */
1951		NULL,					/* ea_list */
1952		&fsp,					/* result */
1953		&smb_action);				/* pinfo */
1954
1955	if (!NT_STATUS_IS_OK(status)) {
1956		if (open_was_deferred(req->mid)) {
1957			/* We have re-scheduled this call. */
1958			goto out;
1959		}
1960		reply_openerror(req, status);
1961		goto out;
1962	}
1963
1964	/* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1965	   if the file is truncated or created. */
1966	if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1967		fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1968		if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1969			close_file(req, fsp, ERROR_CLOSE);
1970			reply_nterror(req, NT_STATUS_DISK_FULL);
1971			goto out;
1972		}
1973		retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1974		if (retval < 0) {
1975			close_file(req, fsp, ERROR_CLOSE);
1976			reply_nterror(req, NT_STATUS_DISK_FULL);
1977			goto out;
1978		}
1979		smb_fname->st.st_ex_size =
1980		    SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &smb_fname->st);
1981	}
1982
1983	fattr = dos_mode(conn, smb_fname);
1984	mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1985	if (fattr & aDIR) {
1986		close_file(req, fsp, ERROR_CLOSE);
1987		reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1988		goto out;
1989	}
1990
1991	/* If the caller set the extended oplock request bit
1992		and we granted one (by whatever means) - set the
1993		correct bit for extended oplock reply.
1994	*/
1995
1996	if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1997		smb_action |= EXTENDED_OPLOCK_GRANTED;
1998	}
1999
2000	if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2001		smb_action |= EXTENDED_OPLOCK_GRANTED;
2002	}
2003
2004	/* If the caller set the core oplock request bit
2005		and we granted one (by whatever means) - set the
2006		correct bit for core oplock reply.
2007	*/
2008
2009	if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2010		reply_outbuf(req, 19, 0);
2011	} else {
2012		reply_outbuf(req, 15, 0);
2013	}
2014
2015	if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
2016		SCVAL(req->outbuf, smb_flg,
2017		      CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2018	}
2019
2020	if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2021		SCVAL(req->outbuf, smb_flg,
2022		      CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2023	}
2024
2025	SSVAL(req->outbuf,smb_vwv2,fsp->fnum);
2026	SSVAL(req->outbuf,smb_vwv3,fattr);
2027	if(lp_dos_filetime_resolution(SNUM(conn)) ) {
2028		srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime & ~1);
2029	} else {
2030		srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime);
2031	}
2032	SIVAL(req->outbuf,smb_vwv6,(uint32)smb_fname->st.st_ex_size);
2033	SSVAL(req->outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
2034	SSVAL(req->outbuf,smb_vwv11,smb_action);
2035
2036	if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
2037		SIVAL(req->outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
2038	}
2039
2040	chain_reply(req);
2041 out:
2042	TALLOC_FREE(smb_fname);
2043	END_PROFILE(SMBopenX);
2044	return;
2045}
2046
2047/****************************************************************************
2048 Reply to a SMBulogoffX.
2049****************************************************************************/
2050
2051void reply_ulogoffX(struct smb_request *req)
2052{
2053	struct smbd_server_connection *sconn = smbd_server_conn;
2054	user_struct *vuser;
2055
2056	START_PROFILE(SMBulogoffX);
2057
2058	vuser = get_valid_user_struct(sconn, req->vuid);
2059
2060	if(vuser == NULL) {
2061		DEBUG(3,("ulogoff, vuser id %d does not map to user.\n",
2062			 req->vuid));
2063	}
2064
2065	/* in user level security we are supposed to close any files
2066		open by this user */
2067	if ((vuser != NULL) && (lp_security() != SEC_SHARE)) {
2068		file_close_user(req->vuid);
2069	}
2070
2071	invalidate_vuid(sconn, req->vuid);
2072
2073	reply_outbuf(req, 2, 0);
2074
2075	DEBUG( 3, ( "ulogoffX vuid=%d\n", req->vuid ) );
2076
2077	END_PROFILE(SMBulogoffX);
2078	req->vuid = UID_FIELD_INVALID;
2079	chain_reply(req);
2080}
2081
2082/****************************************************************************
2083 Reply to a mknew or a create.
2084****************************************************************************/
2085
2086void reply_mknew(struct smb_request *req)
2087{
2088	connection_struct *conn = req->conn;
2089	struct smb_filename *smb_fname = NULL;
2090	char *fname = NULL;
2091	uint32 fattr = 0;
2092	struct smb_file_time ft;
2093	files_struct *fsp;
2094	int oplock_request = 0;
2095	NTSTATUS status;
2096	uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
2097	uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
2098	uint32 create_disposition;
2099	uint32 create_options = 0;
2100	TALLOC_CTX *ctx = talloc_tos();
2101
2102	START_PROFILE(SMBcreate);
2103	ZERO_STRUCT(ft);
2104
2105        if (req->wct < 3) {
2106		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2107		goto out;
2108	}
2109
2110	fattr = SVAL(req->vwv+0, 0);
2111	oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2112
2113	/* mtime. */
2114	ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
2115
2116	srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
2117			    STR_TERMINATE, &status);
2118	if (!NT_STATUS_IS_OK(status)) {
2119		reply_nterror(req, status);
2120		goto out;
2121	}
2122
2123	status = filename_convert(ctx,
2124				conn,
2125				req->flags2 & FLAGS2_DFS_PATHNAMES,
2126				fname,
2127				0,
2128				NULL,
2129				&smb_fname);
2130	if (!NT_STATUS_IS_OK(status)) {
2131		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2132			reply_botherror(req,
2133					NT_STATUS_PATH_NOT_COVERED,
2134					ERRSRV, ERRbadpath);
2135			goto out;
2136		}
2137		reply_nterror(req, status);
2138		goto out;
2139	}
2140
2141	if (fattr & aVOLID) {
2142		DEBUG(0,("Attempt to create file (%s) with volid set - "
2143			 "please report this\n",
2144			 smb_fname_str_dbg(smb_fname)));
2145	}
2146
2147	if(req->cmd == SMBmknew) {
2148		/* We should fail if file exists. */
2149		create_disposition = FILE_CREATE;
2150	} else {
2151		/* Create if file doesn't exist, truncate if it does. */
2152		create_disposition = FILE_OVERWRITE_IF;
2153	}
2154
2155	status = SMB_VFS_CREATE_FILE(
2156		conn,					/* conn */
2157		req,					/* req */
2158		0,					/* root_dir_fid */
2159		smb_fname,				/* fname */
2160		access_mask,				/* access_mask */
2161		share_mode,				/* share_access */
2162		create_disposition,			/* create_disposition*/
2163		create_options,				/* create_options */
2164		fattr,					/* file_attributes */
2165		oplock_request,				/* oplock_request */
2166		0,					/* allocation_size */
2167		NULL,					/* sd */
2168		NULL,					/* ea_list */
2169		&fsp,					/* result */
2170		NULL);					/* pinfo */
2171
2172	if (!NT_STATUS_IS_OK(status)) {
2173		if (open_was_deferred(req->mid)) {
2174			/* We have re-scheduled this call. */
2175			goto out;
2176		}
2177		reply_openerror(req, status);
2178		goto out;
2179	}
2180
2181	ft.atime = smb_fname->st.st_ex_atime; /* atime. */
2182	status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
2183	if (!NT_STATUS_IS_OK(status)) {
2184		END_PROFILE(SMBcreate);
2185		goto out;
2186	}
2187
2188	reply_outbuf(req, 1, 0);
2189	SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2190
2191	if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2192		SCVAL(req->outbuf,smb_flg,
2193				CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2194	}
2195
2196	if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2197		SCVAL(req->outbuf,smb_flg,
2198				CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2199	}
2200
2201	DEBUG(2, ("reply_mknew: file %s\n", smb_fname_str_dbg(smb_fname)));
2202	DEBUG(3, ("reply_mknew %s fd=%d dmode=0x%x\n",
2203		  smb_fname_str_dbg(smb_fname), fsp->fh->fd,
2204		  (unsigned int)fattr));
2205
2206 out:
2207	TALLOC_FREE(smb_fname);
2208	END_PROFILE(SMBcreate);
2209	return;
2210}
2211
2212/****************************************************************************
2213 Reply to a create temporary file.
2214****************************************************************************/
2215
2216void reply_ctemp(struct smb_request *req)
2217{
2218	connection_struct *conn = req->conn;
2219	struct smb_filename *smb_fname = NULL;
2220	char *fname = NULL;
2221	uint32 fattr;
2222	files_struct *fsp;
2223	int oplock_request;
2224	int tmpfd;
2225	char *s;
2226	NTSTATUS status;
2227	TALLOC_CTX *ctx = talloc_tos();
2228
2229	START_PROFILE(SMBctemp);
2230
2231	if (req->wct < 3) {
2232		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2233		goto out;
2234	}
2235
2236	fattr = SVAL(req->vwv+0, 0);
2237	oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
2238
2239	srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
2240			    STR_TERMINATE, &status);
2241	if (!NT_STATUS_IS_OK(status)) {
2242		reply_nterror(req, status);
2243		goto out;
2244	}
2245	if (*fname) {
2246		fname = talloc_asprintf(ctx,
2247				"%s/TMXXXXXX",
2248				fname);
2249	} else {
2250		fname = talloc_strdup(ctx, "TMXXXXXX");
2251	}
2252
2253	if (!fname) {
2254		reply_nterror(req, NT_STATUS_NO_MEMORY);
2255		goto out;
2256	}
2257
2258	status = filename_convert(ctx, conn,
2259				req->flags2 & FLAGS2_DFS_PATHNAMES,
2260				fname,
2261				0,
2262				NULL,
2263				&smb_fname);
2264	if (!NT_STATUS_IS_OK(status)) {
2265		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2266			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2267					ERRSRV, ERRbadpath);
2268			goto out;
2269		}
2270		reply_nterror(req, status);
2271		goto out;
2272	}
2273
2274	tmpfd = mkstemp(smb_fname->base_name);
2275	if (tmpfd == -1) {
2276		reply_nterror(req, map_nt_error_from_unix(errno));
2277		goto out;
2278	}
2279
2280	SMB_VFS_STAT(conn, smb_fname);
2281
2282	/* We should fail if file does not exist. */
2283	status = SMB_VFS_CREATE_FILE(
2284		conn,					/* conn */
2285		req,					/* req */
2286		0,					/* root_dir_fid */
2287		smb_fname,				/* fname */
2288		FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
2289		FILE_SHARE_READ | FILE_SHARE_WRITE,	/* share_access */
2290		FILE_OPEN,				/* create_disposition*/
2291		0,					/* create_options */
2292		fattr,					/* file_attributes */
2293		oplock_request,				/* oplock_request */
2294		0,					/* allocation_size */
2295		NULL,					/* sd */
2296		NULL,					/* ea_list */
2297		&fsp,					/* result */
2298		NULL);					/* pinfo */
2299
2300	/* close fd from mkstemp() */
2301	close(tmpfd);
2302
2303	if (!NT_STATUS_IS_OK(status)) {
2304		if (open_was_deferred(req->mid)) {
2305			/* We have re-scheduled this call. */
2306			goto out;
2307		}
2308		reply_openerror(req, status);
2309		goto out;
2310	}
2311
2312	reply_outbuf(req, 1, 0);
2313	SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
2314
2315	/* the returned filename is relative to the directory */
2316	s = strrchr_m(fsp->fsp_name->base_name, '/');
2317	if (!s) {
2318		s = fsp->fsp_name->base_name;
2319	} else {
2320		s++;
2321	}
2322
2323#if 0
2324	/* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
2325	   thing in the byte section. JRA */
2326	SSVALS(p, 0, -1); /* what is this? not in spec */
2327#endif
2328	if (message_push_string(&req->outbuf, s, STR_ASCII|STR_TERMINATE)
2329	    == -1) {
2330		reply_nterror(req, NT_STATUS_NO_MEMORY);
2331		goto out;
2332	}
2333
2334	if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
2335		SCVAL(req->outbuf, smb_flg,
2336		      CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2337	}
2338
2339	if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
2340		SCVAL(req->outbuf, smb_flg,
2341		      CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
2342	}
2343
2344	DEBUG(2, ("reply_ctemp: created temp file %s\n", fsp_str_dbg(fsp)));
2345	DEBUG(3, ("reply_ctemp %s fd=%d umode=0%o\n", fsp_str_dbg(fsp),
2346		    fsp->fh->fd, (unsigned int)smb_fname->st.st_ex_mode));
2347 out:
2348	TALLOC_FREE(smb_fname);
2349	END_PROFILE(SMBctemp);
2350	return;
2351}
2352
2353/*******************************************************************
2354 Check if a user is allowed to rename a file.
2355********************************************************************/
2356
2357static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
2358			uint16 dirtype)
2359{
2360	uint32 fmode;
2361
2362	if (!CAN_WRITE(conn)) {
2363		return NT_STATUS_MEDIA_WRITE_PROTECTED;
2364	}
2365
2366	fmode = dos_mode(conn, fsp->fsp_name);
2367	if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
2368		return NT_STATUS_NO_SUCH_FILE;
2369	}
2370
2371	if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
2372		if (fsp->posix_open) {
2373			return NT_STATUS_OK;
2374		}
2375
2376		/* If no pathnames are open below this
2377		   directory, allow the rename. */
2378
2379		if (file_find_subpath(fsp)) {
2380			return NT_STATUS_ACCESS_DENIED;
2381		}
2382		return NT_STATUS_OK;
2383	}
2384
2385	if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
2386		return NT_STATUS_OK;
2387	}
2388
2389	return NT_STATUS_ACCESS_DENIED;
2390}
2391
2392/*******************************************************************
2393 * unlink a file with all relevant access checks
2394 *******************************************************************/
2395
2396static NTSTATUS do_unlink(connection_struct *conn,
2397			struct smb_request *req,
2398			struct smb_filename *smb_fname,
2399			uint32 dirtype)
2400{
2401	uint32 fattr;
2402	files_struct *fsp;
2403	uint32 dirtype_orig = dirtype;
2404	NTSTATUS status;
2405	int ret;
2406	bool posix_paths = lp_posix_pathnames();
2407
2408	DEBUG(10,("do_unlink: %s, dirtype = %d\n",
2409		  smb_fname_str_dbg(smb_fname),
2410		  dirtype));
2411
2412	if (!CAN_WRITE(conn)) {
2413		return NT_STATUS_MEDIA_WRITE_PROTECTED;
2414	}
2415
2416	if (posix_paths) {
2417		ret = SMB_VFS_LSTAT(conn, smb_fname);
2418	} else {
2419		ret = SMB_VFS_STAT(conn, smb_fname);
2420	}
2421	if (ret != 0) {
2422		return map_nt_error_from_unix(errno);
2423	}
2424
2425	fattr = dos_mode(conn, smb_fname);
2426
2427	if (dirtype & FILE_ATTRIBUTE_NORMAL) {
2428		dirtype = aDIR|aARCH|aRONLY;
2429	}
2430
2431	dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
2432	if (!dirtype) {
2433		return NT_STATUS_NO_SUCH_FILE;
2434	}
2435
2436	if (!dir_check_ftype(conn, fattr, dirtype)) {
2437		if (fattr & aDIR) {
2438			return NT_STATUS_FILE_IS_A_DIRECTORY;
2439		}
2440		return NT_STATUS_NO_SUCH_FILE;
2441	}
2442
2443	if (dirtype_orig & 0x8000) {
2444		/* These will never be set for POSIX. */
2445		return NT_STATUS_NO_SUCH_FILE;
2446	}
2447
2448#if 0
2449	if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
2450                return NT_STATUS_FILE_IS_A_DIRECTORY;
2451        }
2452
2453        if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
2454                return NT_STATUS_NO_SUCH_FILE;
2455        }
2456
2457	if (dirtype & 0xFF00) {
2458		/* These will never be set for POSIX. */
2459		return NT_STATUS_NO_SUCH_FILE;
2460	}
2461
2462	dirtype &= 0xFF;
2463	if (!dirtype) {
2464		return NT_STATUS_NO_SUCH_FILE;
2465	}
2466
2467	/* Can't delete a directory. */
2468	if (fattr & aDIR) {
2469		return NT_STATUS_FILE_IS_A_DIRECTORY;
2470	}
2471#endif
2472
2473#if 0 /* JRATEST */
2474	else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
2475		return NT_STATUS_OBJECT_NAME_INVALID;
2476#endif /* JRATEST */
2477
2478	/* On open checks the open itself will check the share mode, so
2479	   don't do it here as we'll get it wrong. */
2480
2481	status = SMB_VFS_CREATE_FILE
2482		(conn,			/* conn */
2483		 req,			/* req */
2484		 0,			/* root_dir_fid */
2485		 smb_fname,		/* fname */
2486		 DELETE_ACCESS,		/* access_mask */
2487		 FILE_SHARE_NONE,	/* share_access */
2488		 FILE_OPEN,		/* create_disposition*/
2489		 FILE_NON_DIRECTORY_FILE, /* create_options */
2490		 			/* file_attributes */
2491		 posix_paths ? FILE_FLAG_POSIX_SEMANTICS|0777 :
2492				FILE_ATTRIBUTE_NORMAL,
2493		 0,			/* oplock_request */
2494		 0,			/* allocation_size */
2495		 NULL,			/* sd */
2496		 NULL,			/* ea_list */
2497		 &fsp,			/* result */
2498		 NULL);			/* pinfo */
2499
2500	if (!NT_STATUS_IS_OK(status)) {
2501		DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
2502			   nt_errstr(status)));
2503		return status;
2504	}
2505
2506	status = can_set_delete_on_close(fsp, fattr);
2507	if (!NT_STATUS_IS_OK(status)) {
2508		DEBUG(10, ("do_unlink can_set_delete_on_close for file %s - "
2509			"(%s)\n",
2510			smb_fname_str_dbg(smb_fname),
2511			nt_errstr(status)));
2512		close_file(req, fsp, NORMAL_CLOSE);
2513		return status;
2514	}
2515
2516	/* The set is across all open files on this dev/inode pair. */
2517	if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
2518		close_file(req, fsp, NORMAL_CLOSE);
2519		return NT_STATUS_ACCESS_DENIED;
2520	}
2521
2522	return close_file(req, fsp, NORMAL_CLOSE);
2523}
2524
2525/****************************************************************************
2526 The guts of the unlink command, split out so it may be called by the NT SMB
2527 code.
2528****************************************************************************/
2529
2530NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
2531			  uint32 dirtype, struct smb_filename *smb_fname,
2532			  bool has_wild)
2533{
2534	char *fname_dir = NULL;
2535	char *fname_mask = NULL;
2536	int count=0;
2537	NTSTATUS status = NT_STATUS_OK;
2538	TALLOC_CTX *ctx = talloc_tos();
2539
2540	/* Split up the directory from the filename/mask. */
2541	status = split_fname_dir_mask(ctx, smb_fname->base_name,
2542				      &fname_dir, &fname_mask);
2543	if (!NT_STATUS_IS_OK(status)) {
2544		goto out;
2545	}
2546
2547	/*
2548	 * We should only check the mangled cache
2549	 * here if unix_convert failed. This means
2550	 * that the path in 'mask' doesn't exist
2551	 * on the file system and so we need to look
2552	 * for a possible mangle. This patch from
2553	 * Tine Smukavec <valentin.smukavec@hermes.si>.
2554	 */
2555
2556	if (!VALID_STAT(smb_fname->st) &&
2557	    mangle_is_mangled(fname_mask, conn->params)) {
2558		char *new_mask = NULL;
2559		mangle_lookup_name_from_8_3(ctx, fname_mask,
2560					    &new_mask, conn->params);
2561		if (new_mask) {
2562			TALLOC_FREE(fname_mask);
2563			fname_mask = new_mask;
2564		}
2565	}
2566
2567	if (!has_wild) {
2568
2569		/*
2570		 * Only one file needs to be unlinked. Append the mask back
2571		 * onto the directory.
2572		 */
2573		TALLOC_FREE(smb_fname->base_name);
2574		smb_fname->base_name = talloc_asprintf(smb_fname,
2575						       "%s/%s",
2576						       fname_dir,
2577						       fname_mask);
2578		if (!smb_fname->base_name) {
2579			status = NT_STATUS_NO_MEMORY;
2580			goto out;
2581		}
2582		if (dirtype == 0) {
2583			dirtype = FILE_ATTRIBUTE_NORMAL;
2584		}
2585
2586		status = check_name(conn, smb_fname->base_name);
2587		if (!NT_STATUS_IS_OK(status)) {
2588			goto out;
2589		}
2590
2591		status = do_unlink(conn, req, smb_fname, dirtype);
2592		if (!NT_STATUS_IS_OK(status)) {
2593			goto out;
2594		}
2595
2596		count++;
2597	} else {
2598		struct smb_Dir *dir_hnd = NULL;
2599		long offset = 0;
2600		const char *dname = NULL;
2601		char *talloced = NULL;
2602
2603		if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2604			status = NT_STATUS_OBJECT_NAME_INVALID;
2605			goto out;
2606		}
2607
2608		if (strequal(fname_mask,"????????.???")) {
2609			TALLOC_FREE(fname_mask);
2610			fname_mask = talloc_strdup(ctx, "*");
2611			if (!fname_mask) {
2612				status = NT_STATUS_NO_MEMORY;
2613				goto out;
2614			}
2615		}
2616
2617		status = check_name(conn, fname_dir);
2618		if (!NT_STATUS_IS_OK(status)) {
2619			goto out;
2620		}
2621
2622		dir_hnd = OpenDir(talloc_tos(), conn, fname_dir, fname_mask,
2623				  dirtype);
2624		if (dir_hnd == NULL) {
2625			status = map_nt_error_from_unix(errno);
2626			goto out;
2627		}
2628
2629		/* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2630		   the pattern matches against the long name, otherwise the short name
2631		   We don't implement this yet XXXX
2632		*/
2633
2634		status = NT_STATUS_NO_SUCH_FILE;
2635
2636		while ((dname = ReadDirName(dir_hnd, &offset,
2637					    &smb_fname->st, &talloced))) {
2638			TALLOC_CTX *frame = talloc_stackframe();
2639
2640			if (!is_visible_file(conn, fname_dir, dname,
2641					     &smb_fname->st, true)) {
2642				TALLOC_FREE(frame);
2643				TALLOC_FREE(talloced);
2644				continue;
2645			}
2646
2647			/* Quick check for "." and ".." */
2648			if (ISDOT(dname) || ISDOTDOT(dname)) {
2649				TALLOC_FREE(frame);
2650				TALLOC_FREE(talloced);
2651				continue;
2652			}
2653
2654			if(!mask_match(dname, fname_mask,
2655				       conn->case_sensitive)) {
2656				TALLOC_FREE(frame);
2657				TALLOC_FREE(talloced);
2658				continue;
2659			}
2660
2661			TALLOC_FREE(smb_fname->base_name);
2662			smb_fname->base_name =
2663			    talloc_asprintf(smb_fname, "%s/%s",
2664					    fname_dir, dname);
2665
2666			if (!smb_fname->base_name) {
2667				TALLOC_FREE(dir_hnd);
2668				status = NT_STATUS_NO_MEMORY;
2669				TALLOC_FREE(frame);
2670				TALLOC_FREE(talloced);
2671				goto out;
2672			}
2673
2674			status = check_name(conn, smb_fname->base_name);
2675			if (!NT_STATUS_IS_OK(status)) {
2676				TALLOC_FREE(dir_hnd);
2677				TALLOC_FREE(frame);
2678				TALLOC_FREE(talloced);
2679				goto out;
2680			}
2681
2682			status = do_unlink(conn, req, smb_fname, dirtype);
2683			if (!NT_STATUS_IS_OK(status)) {
2684				TALLOC_FREE(frame);
2685				TALLOC_FREE(talloced);
2686				continue;
2687			}
2688
2689			count++;
2690			DEBUG(3,("unlink_internals: successful unlink [%s]\n",
2691				 smb_fname->base_name));
2692
2693			TALLOC_FREE(frame);
2694			TALLOC_FREE(talloced);
2695		}
2696		TALLOC_FREE(dir_hnd);
2697	}
2698
2699	if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
2700		status = map_nt_error_from_unix(errno);
2701	}
2702
2703 out:
2704	TALLOC_FREE(fname_dir);
2705	TALLOC_FREE(fname_mask);
2706	return status;
2707}
2708
2709/****************************************************************************
2710 Reply to a unlink
2711****************************************************************************/
2712
2713void reply_unlink(struct smb_request *req)
2714{
2715	connection_struct *conn = req->conn;
2716	char *name = NULL;
2717	struct smb_filename *smb_fname = NULL;
2718	uint32 dirtype;
2719	NTSTATUS status;
2720	bool path_contains_wcard = False;
2721	TALLOC_CTX *ctx = talloc_tos();
2722
2723	START_PROFILE(SMBunlink);
2724
2725	if (req->wct < 1) {
2726		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2727		goto out;
2728	}
2729
2730	dirtype = SVAL(req->vwv+0, 0);
2731
2732	srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
2733				  STR_TERMINATE, &status,
2734				  &path_contains_wcard);
2735	if (!NT_STATUS_IS_OK(status)) {
2736		reply_nterror(req, status);
2737		goto out;
2738	}
2739
2740	status = filename_convert(ctx, conn,
2741				  req->flags2 & FLAGS2_DFS_PATHNAMES,
2742				  name,
2743				  UCF_COND_ALLOW_WCARD_LCOMP,
2744				  &path_contains_wcard,
2745				  &smb_fname);
2746	if (!NT_STATUS_IS_OK(status)) {
2747		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2748			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2749					ERRSRV, ERRbadpath);
2750			goto out;
2751		}
2752		reply_nterror(req, status);
2753		goto out;
2754	}
2755
2756	DEBUG(3,("reply_unlink : %s\n", smb_fname_str_dbg(smb_fname)));
2757
2758	status = unlink_internals(conn, req, dirtype, smb_fname,
2759				  path_contains_wcard);
2760	if (!NT_STATUS_IS_OK(status)) {
2761		if (open_was_deferred(req->mid)) {
2762			/* We have re-scheduled this call. */
2763			goto out;
2764		}
2765		reply_nterror(req, status);
2766		goto out;
2767	}
2768
2769	reply_outbuf(req, 0, 0);
2770 out:
2771	TALLOC_FREE(smb_fname);
2772	END_PROFILE(SMBunlink);
2773	return;
2774}
2775
2776/****************************************************************************
2777 Fail for readbraw.
2778****************************************************************************/
2779
2780static void fail_readraw(void)
2781{
2782	const char *errstr = talloc_asprintf(talloc_tos(),
2783			"FAIL ! reply_readbraw: socket write fail (%s)",
2784			strerror(errno));
2785	if (!errstr) {
2786		errstr = "";
2787	}
2788	exit_server_cleanly(errstr);
2789}
2790
2791/****************************************************************************
2792 Fake (read/write) sendfile. Returns -1 on read or write fail.
2793****************************************************************************/
2794
2795static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos,
2796			     size_t nread)
2797{
2798	size_t bufsize;
2799	size_t tosend = nread;
2800	char *buf;
2801
2802	if (nread == 0) {
2803		return 0;
2804	}
2805
2806	bufsize = MIN(nread, 65536);
2807
2808	if (!(buf = SMB_MALLOC_ARRAY(char, bufsize))) {
2809		return -1;
2810	}
2811
2812	while (tosend > 0) {
2813		ssize_t ret;
2814		size_t cur_read;
2815
2816		if (tosend > bufsize) {
2817			cur_read = bufsize;
2818		} else {
2819			cur_read = tosend;
2820		}
2821		ret = read_file(fsp,buf,startpos,cur_read);
2822		if (ret == -1) {
2823			SAFE_FREE(buf);
2824			return -1;
2825		}
2826
2827		/* If we had a short read, fill with zeros. */
2828		if (ret < cur_read) {
2829			memset(buf + ret, '\0', cur_read - ret);
2830		}
2831
2832		if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
2833			SAFE_FREE(buf);
2834			return -1;
2835		}
2836		tosend -= cur_read;
2837		startpos += cur_read;
2838	}
2839
2840	SAFE_FREE(buf);
2841	return (ssize_t)nread;
2842}
2843
2844#if defined(WITH_SENDFILE)
2845/****************************************************************************
2846 Deal with the case of sendfile reading less bytes from the file than
2847 requested. Fill with zeros (all we can do).
2848****************************************************************************/
2849
2850static void sendfile_short_send(files_struct *fsp,
2851				ssize_t nread,
2852				size_t headersize,
2853				size_t smb_maxcnt)
2854{
2855#define SHORT_SEND_BUFSIZE 1024
2856	if (nread < headersize) {
2857		DEBUG(0,("sendfile_short_send: sendfile failed to send "
2858			"header for file %s (%s). Terminating\n",
2859			fsp_str_dbg(fsp), strerror(errno)));
2860		exit_server_cleanly("sendfile_short_send failed");
2861	}
2862
2863	nread -= headersize;
2864
2865	if (nread < smb_maxcnt) {
2866		char *buf = SMB_CALLOC_ARRAY(char, SHORT_SEND_BUFSIZE);
2867		if (!buf) {
2868			exit_server_cleanly("sendfile_short_send: "
2869				"malloc failed");
2870		}
2871
2872		DEBUG(0,("sendfile_short_send: filling truncated file %s "
2873			"with zeros !\n", fsp_str_dbg(fsp)));
2874
2875		while (nread < smb_maxcnt) {
2876			/*
2877			 * We asked for the real file size and told sendfile
2878			 * to not go beyond the end of the file. But it can
2879			 * happen that in between our fstat call and the
2880			 * sendfile call the file was truncated. This is very
2881			 * bad because we have already announced the larger
2882			 * number of bytes to the client.
2883			 *
2884			 * The best we can do now is to send 0-bytes, just as
2885			 * a read from a hole in a sparse file would do.
2886			 *
2887			 * This should happen rarely enough that I don't care
2888			 * about efficiency here :-)
2889			 */
2890			size_t to_write;
2891
2892			to_write = MIN(SHORT_SEND_BUFSIZE, smb_maxcnt - nread);
2893			if (write_data(smbd_server_fd(), buf, to_write) != to_write) {
2894				exit_server_cleanly("sendfile_short_send: "
2895					"write_data failed");
2896			}
2897			nread += to_write;
2898		}
2899		SAFE_FREE(buf);
2900	}
2901}
2902#endif /* defined WITH_SENDFILE */
2903
2904/****************************************************************************
2905 Return a readbraw error (4 bytes of zero).
2906****************************************************************************/
2907
2908static void reply_readbraw_error(void)
2909{
2910	char header[4];
2911	SIVAL(header,0,0);
2912	if (write_data(smbd_server_fd(),header,4) != 4) {
2913		fail_readraw();
2914	}
2915}
2916
2917/****************************************************************************
2918 Use sendfile in readbraw.
2919****************************************************************************/
2920
2921static void send_file_readbraw(connection_struct *conn,
2922			       struct smb_request *req,
2923			       files_struct *fsp,
2924			       SMB_OFF_T startpos,
2925			       size_t nread,
2926			       ssize_t mincount)
2927{
2928	char *outbuf = NULL;
2929	ssize_t ret=0;
2930
2931#if defined(WITH_SENDFILE)
2932	/*
2933	 * We can only use sendfile on a non-chained packet
2934	 * but we can use on a non-oplocked file. tridge proved this
2935	 * on a train in Germany :-). JRA.
2936	 * reply_readbraw has already checked the length.
2937	 */
2938
2939	if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
2940	    (fsp->wcp == NULL) &&
2941	    lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
2942		ssize_t sendfile_read = -1;
2943		char header[4];
2944		DATA_BLOB header_blob;
2945
2946		_smb_setlen(header,nread);
2947		header_blob = data_blob_const(header, 4);
2948
2949		if ((sendfile_read = SMB_VFS_SENDFILE(smbd_server_fd(), fsp,
2950				&header_blob, startpos, nread)) == -1) {
2951			/* Returning ENOSYS means no data at all was sent.
2952			 * Do this as a normal read. */
2953			if (errno == ENOSYS) {
2954				goto normal_readbraw;
2955			}
2956
2957			/*
2958			 * Special hack for broken Linux with no working sendfile. If we
2959			 * return EINTR we sent the header but not the rest of the data.
2960			 * Fake this up by doing read/write calls.
2961			 */
2962			if (errno == EINTR) {
2963				/* Ensure we don't do this again. */
2964				set_use_sendfile(SNUM(conn), False);
2965				DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2966
2967				if (fake_sendfile(fsp, startpos, nread) == -1) {
2968					DEBUG(0,("send_file_readbraw: "
2969						 "fake_sendfile failed for "
2970						 "file %s (%s).\n",
2971						 fsp_str_dbg(fsp),
2972						 strerror(errno)));
2973					exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2974				}
2975				return;
2976			}
2977
2978			DEBUG(0,("send_file_readbraw: sendfile failed for "
2979				 "file %s (%s). Terminating\n",
2980				 fsp_str_dbg(fsp), strerror(errno)));
2981			exit_server_cleanly("send_file_readbraw sendfile failed");
2982		} else if (sendfile_read == 0) {
2983			/*
2984			 * Some sendfile implementations return 0 to indicate
2985			 * that there was a short read, but nothing was
2986			 * actually written to the socket.  In this case,
2987			 * fallback to the normal read path so the header gets
2988			 * the correct byte count.
2989			 */
2990			DEBUG(3, ("send_file_readbraw: sendfile sent zero "
2991				  "bytes falling back to the normal read: "
2992				  "%s\n", fsp_str_dbg(fsp)));
2993			goto normal_readbraw;
2994		}
2995
2996		/* Deal with possible short send. */
2997		if (sendfile_read != 4+nread) {
2998			sendfile_short_send(fsp, sendfile_read, 4, nread);
2999		}
3000		return;
3001	}
3002
3003normal_readbraw:
3004#endif
3005
3006	outbuf = TALLOC_ARRAY(NULL, char, nread+4);
3007	if (!outbuf) {
3008		DEBUG(0,("send_file_readbraw: TALLOC_ARRAY failed for size %u.\n",
3009			(unsigned)(nread+4)));
3010		reply_readbraw_error();
3011		return;
3012	}
3013
3014	if (nread > 0) {
3015		ret = read_file(fsp,outbuf+4,startpos,nread);
3016#if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3017		if (ret < mincount)
3018			ret = 0;
3019#else
3020		if (ret < nread)
3021			ret = 0;
3022#endif
3023	}
3024
3025	_smb_setlen(outbuf,ret);
3026	if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
3027		fail_readraw();
3028
3029	TALLOC_FREE(outbuf);
3030}
3031
3032/****************************************************************************
3033 Reply to a readbraw (core+ protocol).
3034****************************************************************************/
3035
3036void reply_readbraw(struct smb_request *req)
3037{
3038	connection_struct *conn = req->conn;
3039	ssize_t maxcount,mincount;
3040	size_t nread = 0;
3041	SMB_OFF_T startpos;
3042	files_struct *fsp;
3043	struct lock_struct lock;
3044	SMB_OFF_T size = 0;
3045
3046	START_PROFILE(SMBreadbraw);
3047
3048	if (srv_is_signing_active(smbd_server_conn) ||
3049	    is_encrypted_packet(req->inbuf)) {
3050		exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
3051			"raw reads/writes are disallowed.");
3052	}
3053
3054	if (req->wct < 8) {
3055		reply_readbraw_error();
3056		END_PROFILE(SMBreadbraw);
3057		return;
3058	}
3059
3060	/*
3061	 * Special check if an oplock break has been issued
3062	 * and the readraw request croses on the wire, we must
3063	 * return a zero length response here.
3064	 */
3065
3066	fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3067
3068	/*
3069	 * We have to do a check_fsp by hand here, as
3070	 * we must always return 4 zero bytes on error,
3071	 * not a NTSTATUS.
3072	 */
3073
3074	if (!fsp || !conn || conn != fsp->conn ||
3075			req->vuid != fsp->vuid ||
3076			fsp->is_directory || fsp->fh->fd == -1) {
3077		/*
3078		 * fsp could be NULL here so use the value from the packet. JRA.
3079		 */
3080		DEBUG(3,("reply_readbraw: fnum %d not valid "
3081			"- cache prime?\n",
3082			(int)SVAL(req->vwv+0, 0)));
3083		reply_readbraw_error();
3084		END_PROFILE(SMBreadbraw);
3085		return;
3086	}
3087
3088	/* Do a "by hand" version of CHECK_READ. */
3089	if (!(fsp->can_read ||
3090			((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
3091				(fsp->access_mask & FILE_EXECUTE)))) {
3092		DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
3093				(int)SVAL(req->vwv+0, 0)));
3094		reply_readbraw_error();
3095		END_PROFILE(SMBreadbraw);
3096		return;
3097	}
3098
3099	flush_write_cache(fsp, READRAW_FLUSH);
3100
3101	startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
3102	if(req->wct == 10) {
3103		/*
3104		 * This is a large offset (64 bit) read.
3105		 */
3106#ifdef LARGE_SMB_OFF_T
3107
3108		startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
3109
3110#else /* !LARGE_SMB_OFF_T */
3111
3112		/*
3113		 * Ensure we haven't been sent a >32 bit offset.
3114		 */
3115
3116		if(IVAL(req->vwv+8, 0) != 0) {
3117			DEBUG(0,("reply_readbraw: large offset "
3118				"(%x << 32) used and we don't support "
3119				"64 bit offsets.\n",
3120			(unsigned int)IVAL(req->vwv+8, 0) ));
3121			reply_readbraw_error();
3122			END_PROFILE(SMBreadbraw);
3123			return;
3124		}
3125
3126#endif /* LARGE_SMB_OFF_T */
3127
3128		if(startpos < 0) {
3129			DEBUG(0,("reply_readbraw: negative 64 bit "
3130				"readraw offset (%.0f) !\n",
3131				(double)startpos ));
3132			reply_readbraw_error();
3133			END_PROFILE(SMBreadbraw);
3134			return;
3135		}
3136	}
3137
3138	maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
3139	mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
3140
3141	/* ensure we don't overrun the packet size */
3142	maxcount = MIN(65535,maxcount);
3143
3144	init_strict_lock_struct(fsp, (uint32)req->smbpid,
3145	    (uint64_t)startpos, (uint64_t)maxcount, READ_LOCK,
3146	    &lock);
3147
3148	if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3149		reply_readbraw_error();
3150		END_PROFILE(SMBreadbraw);
3151		return;
3152	}
3153
3154	if (fsp_stat(fsp) == 0) {
3155		size = fsp->fsp_name->st.st_ex_size;
3156	}
3157
3158	if (startpos >= size) {
3159		nread = 0;
3160	} else {
3161		nread = MIN(maxcount,(size - startpos));
3162	}
3163
3164#if 0 /* mincount appears to be ignored in a W2K server. JRA. */
3165	if (nread < mincount)
3166		nread = 0;
3167#endif
3168
3169	DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
3170		"min=%lu nread=%lu\n",
3171		fsp->fnum, (double)startpos,
3172		(unsigned long)maxcount,
3173		(unsigned long)mincount,
3174		(unsigned long)nread ) );
3175
3176	send_file_readbraw(conn, req, fsp, startpos, nread, mincount);
3177
3178	DEBUG(5,("reply_readbraw finished\n"));
3179
3180	SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3181
3182	END_PROFILE(SMBreadbraw);
3183	return;
3184}
3185
3186#undef DBGC_CLASS
3187#define DBGC_CLASS DBGC_LOCKING
3188
3189/****************************************************************************
3190 Reply to a lockread (core+ protocol).
3191****************************************************************************/
3192
3193void reply_lockread(struct smb_request *req)
3194{
3195	connection_struct *conn = req->conn;
3196	ssize_t nread = -1;
3197	char *data;
3198	SMB_OFF_T startpos;
3199	size_t numtoread;
3200	NTSTATUS status;
3201	files_struct *fsp;
3202	struct byte_range_lock *br_lck = NULL;
3203	char *p = NULL;
3204	struct smbd_server_connection *sconn = smbd_server_conn;
3205
3206	START_PROFILE(SMBlockread);
3207
3208	if (req->wct < 5) {
3209		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3210		END_PROFILE(SMBlockread);
3211		return;
3212	}
3213
3214	fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3215
3216	if (!check_fsp(conn, req, fsp)) {
3217		END_PROFILE(SMBlockread);
3218		return;
3219	}
3220
3221	if (!CHECK_READ(fsp,req)) {
3222		reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3223		END_PROFILE(SMBlockread);
3224		return;
3225	}
3226
3227	numtoread = SVAL(req->vwv+1, 0);
3228	startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3229
3230	numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
3231
3232	reply_outbuf(req, 5, numtoread + 3);
3233
3234	data = smb_buf(req->outbuf) + 3;
3235
3236	/*
3237	 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
3238	 * protocol request that predates the read/write lock concept.
3239	 * Thus instead of asking for a read lock here we need to ask
3240	 * for a write lock. JRA.
3241	 * Note that the requested lock size is unaffected by max_recv.
3242	 */
3243
3244	br_lck = do_lock(smbd_messaging_context(),
3245			fsp,
3246			req->smbpid,
3247			(uint64_t)numtoread,
3248			(uint64_t)startpos,
3249			WRITE_LOCK,
3250			WINDOWS_LOCK,
3251			False, /* Non-blocking lock. */
3252			&status,
3253			NULL,
3254			NULL);
3255	TALLOC_FREE(br_lck);
3256
3257	if (NT_STATUS_V(status)) {
3258		reply_nterror(req, status);
3259		END_PROFILE(SMBlockread);
3260		return;
3261	}
3262
3263	/*
3264	 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
3265	 */
3266
3267	if (numtoread > sconn->smb1.negprot.max_recv) {
3268		DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
3269Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3270			(unsigned int)numtoread,
3271			(unsigned int)sconn->smb1.negprot.max_recv));
3272		numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3273	}
3274	nread = read_file(fsp,data,startpos,numtoread);
3275
3276	if (nread < 0) {
3277		reply_nterror(req, map_nt_error_from_unix(errno));
3278		END_PROFILE(SMBlockread);
3279		return;
3280	}
3281
3282	srv_set_message((char *)req->outbuf, 5, nread+3, False);
3283
3284	SSVAL(req->outbuf,smb_vwv0,nread);
3285	SSVAL(req->outbuf,smb_vwv5,nread+3);
3286	p = smb_buf(req->outbuf);
3287	SCVAL(p,0,0); /* pad byte. */
3288	SSVAL(p,1,nread);
3289
3290	DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
3291		 fsp->fnum, (int)numtoread, (int)nread));
3292
3293	END_PROFILE(SMBlockread);
3294	return;
3295}
3296
3297#undef DBGC_CLASS
3298#define DBGC_CLASS DBGC_ALL
3299
3300/****************************************************************************
3301 Reply to a read.
3302****************************************************************************/
3303
3304void reply_read(struct smb_request *req)
3305{
3306	connection_struct *conn = req->conn;
3307	size_t numtoread;
3308	ssize_t nread = 0;
3309	char *data;
3310	SMB_OFF_T startpos;
3311	int outsize = 0;
3312	files_struct *fsp;
3313	struct lock_struct lock;
3314	struct smbd_server_connection *sconn = smbd_server_conn;
3315
3316	START_PROFILE(SMBread);
3317
3318	if (req->wct < 3) {
3319		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3320		END_PROFILE(SMBread);
3321		return;
3322	}
3323
3324	fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3325
3326	if (!check_fsp(conn, req, fsp)) {
3327		END_PROFILE(SMBread);
3328		return;
3329	}
3330
3331	if (!CHECK_READ(fsp,req)) {
3332		reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3333		END_PROFILE(SMBread);
3334		return;
3335	}
3336
3337	numtoread = SVAL(req->vwv+1, 0);
3338	startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3339
3340	numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
3341
3342	/*
3343	 * The requested read size cannot be greater than max_recv. JRA.
3344	 */
3345	if (numtoread > sconn->smb1.negprot.max_recv) {
3346		DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
3347Returning short read of maximum allowed for compatibility with Windows 2000.\n",
3348			(unsigned int)numtoread,
3349			(unsigned int)sconn->smb1.negprot.max_recv));
3350		numtoread = MIN(numtoread, sconn->smb1.negprot.max_recv);
3351	}
3352
3353	reply_outbuf(req, 5, numtoread+3);
3354
3355	data = smb_buf(req->outbuf) + 3;
3356
3357	init_strict_lock_struct(fsp, (uint32)req->smbpid,
3358	    (uint64_t)startpos, (uint64_t)numtoread, READ_LOCK,
3359	    &lock);
3360
3361	if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3362		reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3363		END_PROFILE(SMBread);
3364		return;
3365	}
3366
3367	if (numtoread > 0)
3368		nread = read_file(fsp,data,startpos,numtoread);
3369
3370	if (nread < 0) {
3371		reply_nterror(req, map_nt_error_from_unix(errno));
3372		goto strict_unlock;
3373	}
3374
3375	srv_set_message((char *)req->outbuf, 5, nread+3, False);
3376
3377	SSVAL(req->outbuf,smb_vwv0,nread);
3378	SSVAL(req->outbuf,smb_vwv5,nread+3);
3379	SCVAL(smb_buf(req->outbuf),0,1);
3380	SSVAL(smb_buf(req->outbuf),1,nread);
3381
3382	DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
3383		fsp->fnum, (int)numtoread, (int)nread ) );
3384
3385strict_unlock:
3386	SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3387
3388	END_PROFILE(SMBread);
3389	return;
3390}
3391
3392/****************************************************************************
3393 Setup readX header.
3394****************************************************************************/
3395
3396static int setup_readX_header(struct smb_request *req, char *outbuf,
3397			      size_t smb_maxcnt)
3398{
3399	int outsize;
3400	char *data;
3401
3402	outsize = srv_set_message(outbuf,12,smb_maxcnt,False);
3403	data = smb_buf(outbuf);
3404
3405	memset(outbuf+smb_vwv0,'\0',24); /* valgrind init. */
3406
3407	SCVAL(outbuf,smb_vwv0,0xFF);
3408	SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
3409	SSVAL(outbuf,smb_vwv5,smb_maxcnt);
3410	SSVAL(outbuf,smb_vwv6,
3411	      req_wct_ofs(req)
3412	      + 1 		/* the wct field */
3413	      + 12 * sizeof(uint16_t) /* vwv */
3414	      + 2);		/* the buflen field */
3415	SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
3416	SSVAL(outbuf,smb_vwv11,smb_maxcnt);
3417	/* Reset the outgoing length, set_message truncates at 0x1FFFF. */
3418	_smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
3419	return outsize;
3420}
3421
3422/****************************************************************************
3423 Reply to a read and X - possibly using sendfile.
3424****************************************************************************/
3425
3426static void send_file_readX(connection_struct *conn, struct smb_request *req,
3427			    files_struct *fsp, SMB_OFF_T startpos,
3428			    size_t smb_maxcnt)
3429{
3430	ssize_t nread = -1;
3431	struct lock_struct lock;
3432	int saved_errno = 0;
3433
3434	if(fsp_stat(fsp) == -1) {
3435		reply_nterror(req, map_nt_error_from_unix(errno));
3436		return;
3437	}
3438
3439	init_strict_lock_struct(fsp, (uint32)req->smbpid,
3440	    (uint64_t)startpos, (uint64_t)smb_maxcnt, READ_LOCK,
3441	    &lock);
3442
3443	if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3444		reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3445		return;
3446	}
3447
3448	if (!S_ISREG(fsp->fsp_name->st.st_ex_mode) ||
3449			(startpos > fsp->fsp_name->st.st_ex_size)
3450			|| (smb_maxcnt > (fsp->fsp_name->st.st_ex_size - startpos))) {
3451		/*
3452		 * We already know that we would do a short read, so don't
3453		 * try the sendfile() path.
3454		 */
3455		goto nosendfile_read;
3456	}
3457
3458#if defined(WITH_SENDFILE)
3459	/*
3460	 * We can only use sendfile on a non-chained packet
3461	 * but we can use on a non-oplocked file. tridge proved this
3462	 * on a train in Germany :-). JRA.
3463	 */
3464
3465	if (!req_is_in_chain(req) &&
3466	    !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
3467	    (fsp->wcp == NULL) &&
3468	    lp_use_sendfile(SNUM(conn), smbd_server_conn->smb1.signing_state) ) {
3469		uint8 headerbuf[smb_size + 12 * 2];
3470		DATA_BLOB header;
3471
3472		/*
3473		 * Set up the packet header before send. We
3474		 * assume here the sendfile will work (get the
3475		 * correct amount of data).
3476		 */
3477
3478		header = data_blob_const(headerbuf, sizeof(headerbuf));
3479
3480		construct_reply_common_req(req, (char *)headerbuf);
3481		setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3482
3483		if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
3484			/* Returning ENOSYS means no data at all was sent.
3485			   Do this as a normal read. */
3486			if (errno == ENOSYS) {
3487				goto normal_read;
3488			}
3489
3490			/*
3491			 * Special hack for broken Linux with no working sendfile. If we
3492			 * return EINTR we sent the header but not the rest of the data.
3493			 * Fake this up by doing read/write calls.
3494			 */
3495
3496			if (errno == EINTR) {
3497				/* Ensure we don't do this again. */
3498				set_use_sendfile(SNUM(conn), False);
3499				DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
3500				nread = fake_sendfile(fsp, startpos,
3501						      smb_maxcnt);
3502				if (nread == -1) {
3503					DEBUG(0,("send_file_readX: "
3504						 "fake_sendfile failed for "
3505						 "file %s (%s).\n",
3506						 fsp_str_dbg(fsp),
3507						 strerror(errno)));
3508					exit_server_cleanly("send_file_readX: fake_sendfile failed");
3509				}
3510				DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
3511					fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3512				/* No outbuf here means successful sendfile. */
3513				goto strict_unlock;
3514			}
3515
3516			DEBUG(0,("send_file_readX: sendfile failed for file "
3517				 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3518				 strerror(errno)));
3519			exit_server_cleanly("send_file_readX sendfile failed");
3520		} else if (nread == 0) {
3521			/*
3522			 * Some sendfile implementations return 0 to indicate
3523			 * that there was a short read, but nothing was
3524			 * actually written to the socket.  In this case,
3525			 * fallback to the normal read path so the header gets
3526			 * the correct byte count.
3527			 */
3528			DEBUG(3, ("send_file_readX: sendfile sent zero bytes "
3529				  "falling back to the normal read: %s\n",
3530				  fsp_str_dbg(fsp)));
3531			goto normal_read;
3532		}
3533
3534		DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
3535			fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3536
3537		/* Deal with possible short send. */
3538		if (nread != smb_maxcnt + sizeof(headerbuf)) {
3539			sendfile_short_send(fsp, nread, sizeof(headerbuf), smb_maxcnt);
3540		}
3541		/* No outbuf here means successful sendfile. */
3542		SMB_PERFCOUNT_SET_MSGLEN_OUT(&req->pcd, nread);
3543		SMB_PERFCOUNT_END(&req->pcd);
3544		goto strict_unlock;
3545	}
3546
3547normal_read:
3548
3549#endif
3550
3551	if ((smb_maxcnt & 0xFF0000) > 0x10000) {
3552		uint8 headerbuf[smb_size + 2*12];
3553
3554		construct_reply_common_req(req, (char *)headerbuf);
3555		setup_readX_header(req, (char *)headerbuf, smb_maxcnt);
3556
3557		/* Send out the header. */
3558		if (write_data(smbd_server_fd(), (char *)headerbuf,
3559			       sizeof(headerbuf)) != sizeof(headerbuf)) {
3560			DEBUG(0,("send_file_readX: write_data failed for file "
3561				 "%s (%s). Terminating\n", fsp_str_dbg(fsp),
3562				 strerror(errno)));
3563			exit_server_cleanly("send_file_readX sendfile failed");
3564		}
3565		nread = fake_sendfile(fsp, startpos, smb_maxcnt);
3566		if (nread == -1) {
3567			DEBUG(0,("send_file_readX: fake_sendfile failed for "
3568				 "file %s (%s).\n", fsp_str_dbg(fsp),
3569				 strerror(errno)));
3570			exit_server_cleanly("send_file_readX: fake_sendfile failed");
3571		}
3572		goto strict_unlock;
3573	}
3574
3575nosendfile_read:
3576
3577	reply_outbuf(req, 12, smb_maxcnt);
3578
3579	nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
3580	saved_errno = errno;
3581
3582	SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3583
3584	if (nread < 0) {
3585		reply_nterror(req, map_nt_error_from_unix(saved_errno));
3586		return;
3587	}
3588
3589	setup_readX_header(req, (char *)req->outbuf, nread);
3590
3591	DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
3592		    fsp->fnum, (int)smb_maxcnt, (int)nread ) );
3593
3594	chain_reply(req);
3595	return;
3596
3597 strict_unlock:
3598	SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3599	TALLOC_FREE(req->outbuf);
3600	return;
3601}
3602
3603/****************************************************************************
3604 Reply to a read and X.
3605****************************************************************************/
3606
3607void reply_read_and_X(struct smb_request *req)
3608{
3609	connection_struct *conn = req->conn;
3610	files_struct *fsp;
3611	SMB_OFF_T startpos;
3612	size_t smb_maxcnt;
3613	bool big_readX = False;
3614#if 0
3615	size_t smb_mincnt = SVAL(req->vwv+6, 0);
3616#endif
3617
3618	START_PROFILE(SMBreadX);
3619
3620	if ((req->wct != 10) && (req->wct != 12)) {
3621		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3622		return;
3623	}
3624
3625	fsp = file_fsp(req, SVAL(req->vwv+2, 0));
3626	startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3627	smb_maxcnt = SVAL(req->vwv+5, 0);
3628
3629	/* If it's an IPC, pass off the pipe handler. */
3630	if (IS_IPC(conn)) {
3631		reply_pipe_read_and_X(req);
3632		END_PROFILE(SMBreadX);
3633		return;
3634	}
3635
3636	if (!check_fsp(conn, req, fsp)) {
3637		END_PROFILE(SMBreadX);
3638		return;
3639	}
3640
3641	if (!CHECK_READ(fsp,req)) {
3642		reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3643		END_PROFILE(SMBreadX);
3644		return;
3645	}
3646
3647	if (global_client_caps & CAP_LARGE_READX) {
3648		size_t upper_size = SVAL(req->vwv+7, 0);
3649		smb_maxcnt |= (upper_size<<16);
3650		if (upper_size > 1) {
3651			/* Can't do this on a chained packet. */
3652			if ((CVAL(req->vwv+0, 0) != 0xFF)) {
3653				reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3654				END_PROFILE(SMBreadX);
3655				return;
3656			}
3657			/* We currently don't do this on signed or sealed data. */
3658			if (srv_is_signing_active(smbd_server_conn) ||
3659			    is_encrypted_packet(req->inbuf)) {
3660				reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
3661				END_PROFILE(SMBreadX);
3662				return;
3663			}
3664			/* Is there room in the reply for this data ? */
3665			if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2)))  {
3666				reply_nterror(req,
3667					      NT_STATUS_INVALID_PARAMETER);
3668				END_PROFILE(SMBreadX);
3669				return;
3670			}
3671			big_readX = True;
3672		}
3673	}
3674
3675	if (req->wct == 12) {
3676#ifdef LARGE_SMB_OFF_T
3677		/*
3678		 * This is a large offset (64 bit) read.
3679		 */
3680		startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
3681
3682#else /* !LARGE_SMB_OFF_T */
3683
3684		/*
3685		 * Ensure we haven't been sent a >32 bit offset.
3686		 */
3687
3688		if(IVAL(req->vwv+10, 0) != 0) {
3689			DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
3690				 "used and we don't support 64 bit offsets.\n",
3691				 (unsigned int)IVAL(req->vwv+10, 0) ));
3692			END_PROFILE(SMBreadX);
3693			reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3694			return;
3695		}
3696
3697#endif /* LARGE_SMB_OFF_T */
3698
3699	}
3700
3701	if (!big_readX &&
3702	    schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
3703		goto out;
3704	}
3705
3706	send_file_readX(conn, req, fsp,	startpos, smb_maxcnt);
3707
3708 out:
3709	END_PROFILE(SMBreadX);
3710	return;
3711}
3712
3713/****************************************************************************
3714 Error replies to writebraw must have smb_wct == 1. Fix this up.
3715****************************************************************************/
3716
3717void error_to_writebrawerr(struct smb_request *req)
3718{
3719	uint8 *old_outbuf = req->outbuf;
3720
3721	reply_outbuf(req, 1, 0);
3722
3723	memcpy(req->outbuf, old_outbuf, smb_size);
3724	TALLOC_FREE(old_outbuf);
3725}
3726
3727/****************************************************************************
3728 Reply to a writebraw (core+ or LANMAN1.0 protocol).
3729****************************************************************************/
3730
3731void reply_writebraw(struct smb_request *req)
3732{
3733	connection_struct *conn = req->conn;
3734	char *buf = NULL;
3735	ssize_t nwritten=0;
3736	ssize_t total_written=0;
3737	size_t numtowrite=0;
3738	size_t tcount;
3739	SMB_OFF_T startpos;
3740	char *data=NULL;
3741	bool write_through;
3742	files_struct *fsp;
3743	struct lock_struct lock;
3744	NTSTATUS status;
3745
3746	START_PROFILE(SMBwritebraw);
3747
3748	/*
3749	 * If we ever reply with an error, it must have the SMB command
3750	 * type of SMBwritec, not SMBwriteBraw, as this tells the client
3751	 * we're finished.
3752	 */
3753	SCVAL(req->inbuf,smb_com,SMBwritec);
3754
3755	if (srv_is_signing_active(smbd_server_conn)) {
3756		END_PROFILE(SMBwritebraw);
3757		exit_server_cleanly("reply_writebraw: SMB signing is active - "
3758				"raw reads/writes are disallowed.");
3759	}
3760
3761	if (req->wct < 12) {
3762		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3763		error_to_writebrawerr(req);
3764		END_PROFILE(SMBwritebraw);
3765		return;
3766	}
3767
3768	fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3769	if (!check_fsp(conn, req, fsp)) {
3770		error_to_writebrawerr(req);
3771		END_PROFILE(SMBwritebraw);
3772		return;
3773	}
3774
3775	if (!CHECK_WRITE(fsp)) {
3776		reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3777		error_to_writebrawerr(req);
3778		END_PROFILE(SMBwritebraw);
3779		return;
3780	}
3781
3782	tcount = IVAL(req->vwv+1, 0);
3783	startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
3784	write_through = BITSETW(req->vwv+7,0);
3785
3786	/* We have to deal with slightly different formats depending
3787		on whether we are using the core+ or lanman1.0 protocol */
3788
3789	if(get_Protocol() <= PROTOCOL_COREPLUS) {
3790		numtowrite = SVAL(smb_buf(req->inbuf),-2);
3791		data = smb_buf(req->inbuf);
3792	} else {
3793		numtowrite = SVAL(req->vwv+10, 0);
3794		data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
3795	}
3796
3797	/* Ensure we don't write bytes past the end of this packet. */
3798	if (data + numtowrite > smb_base(req->inbuf) + smb_len(req->inbuf)) {
3799		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3800		error_to_writebrawerr(req);
3801		END_PROFILE(SMBwritebraw);
3802		return;
3803	}
3804
3805	init_strict_lock_struct(fsp, (uint32)req->smbpid,
3806	    (uint64_t)startpos, (uint64_t)tcount, WRITE_LOCK,
3807	    &lock);
3808
3809	if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
3810		reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
3811		error_to_writebrawerr(req);
3812		END_PROFILE(SMBwritebraw);
3813		return;
3814	}
3815
3816	if (numtowrite>0) {
3817		nwritten = write_file(req,fsp,data,startpos,numtowrite);
3818	}
3819
3820	DEBUG(3,("reply_writebraw: initial write fnum=%d start=%.0f num=%d "
3821			"wrote=%d sync=%d\n",
3822		fsp->fnum, (double)startpos, (int)numtowrite,
3823		(int)nwritten, (int)write_through));
3824
3825	if (nwritten < (ssize_t)numtowrite)  {
3826		reply_nterror(req, NT_STATUS_DISK_FULL);
3827		error_to_writebrawerr(req);
3828		goto strict_unlock;
3829	}
3830
3831	total_written = nwritten;
3832
3833	/* Allocate a buffer of 64k + length. */
3834	buf = TALLOC_ARRAY(NULL, char, 65540);
3835	if (!buf) {
3836		reply_nterror(req, NT_STATUS_NO_MEMORY);
3837		error_to_writebrawerr(req);
3838		goto strict_unlock;
3839	}
3840
3841	/* Return a SMBwritebraw message to the redirector to tell
3842	 * it to send more bytes */
3843
3844	memcpy(buf, req->inbuf, smb_size);
3845	srv_set_message(buf,get_Protocol()>PROTOCOL_COREPLUS?1:0,0,True);
3846	SCVAL(buf,smb_com,SMBwritebraw);
3847	SSVALS(buf,smb_vwv0,0xFFFF);
3848	show_msg(buf);
3849	if (!srv_send_smb(smbd_server_fd(),
3850			  buf,
3851			  false, 0, /* no signing */
3852			  IS_CONN_ENCRYPTED(conn),
3853			  &req->pcd)) {
3854		exit_server_cleanly("reply_writebraw: srv_send_smb "
3855			"failed.");
3856	}
3857
3858	/* Now read the raw data into the buffer and write it */
3859	status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
3860				 &numtowrite);
3861	if (!NT_STATUS_IS_OK(status)) {
3862		exit_server_cleanly("secondary writebraw failed");
3863	}
3864
3865	/* Set up outbuf to return the correct size */
3866	reply_outbuf(req, 1, 0);
3867
3868	if (numtowrite != 0) {
3869
3870		if (numtowrite > 0xFFFF) {
3871			DEBUG(0,("reply_writebraw: Oversize secondary write "
3872				"raw requested (%u). Terminating\n",
3873				(unsigned int)numtowrite ));
3874			exit_server_cleanly("secondary writebraw failed");
3875		}
3876
3877		if (tcount > nwritten+numtowrite) {
3878			DEBUG(3,("reply_writebraw: Client overestimated the "
3879				"write %d %d %d\n",
3880				(int)tcount,(int)nwritten,(int)numtowrite));
3881		}
3882
3883		status = read_data(smbd_server_fd(), buf+4, numtowrite);
3884
3885		if (!NT_STATUS_IS_OK(status)) {
3886			DEBUG(0,("reply_writebraw: Oversize secondary write "
3887				 "raw read failed (%s). Terminating\n",
3888				 nt_errstr(status)));
3889			exit_server_cleanly("secondary writebraw failed");
3890		}
3891
3892		nwritten = write_file(req,fsp,buf+4,startpos+nwritten,numtowrite);
3893		if (nwritten == -1) {
3894			TALLOC_FREE(buf);
3895			reply_nterror(req, map_nt_error_from_unix(errno));
3896			error_to_writebrawerr(req);
3897			goto strict_unlock;
3898		}
3899
3900		if (nwritten < (ssize_t)numtowrite) {
3901			SCVAL(req->outbuf,smb_rcls,ERRHRD);
3902			SSVAL(req->outbuf,smb_err,ERRdiskfull);
3903		}
3904
3905		if (nwritten > 0) {
3906			total_written += nwritten;
3907		}
3908 	}
3909
3910	TALLOC_FREE(buf);
3911	SSVAL(req->outbuf,smb_vwv0,total_written);
3912
3913	status = sync_file(conn, fsp, write_through);
3914	if (!NT_STATUS_IS_OK(status)) {
3915		DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
3916			 fsp_str_dbg(fsp), nt_errstr(status)));
3917		reply_nterror(req, status);
3918		error_to_writebrawerr(req);
3919		goto strict_unlock;
3920	}
3921
3922	DEBUG(3,("reply_writebraw: secondart write fnum=%d start=%.0f num=%d "
3923		"wrote=%d\n",
3924		fsp->fnum, (double)startpos, (int)numtowrite,
3925		(int)total_written));
3926
3927	SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3928
3929	/* We won't return a status if write through is not selected - this
3930	 * follows what WfWg does */
3931	END_PROFILE(SMBwritebraw);
3932
3933	if (!write_through && total_written==tcount) {
3934
3935#if RABBIT_PELLET_FIX
3936		/*
3937		 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
3938		 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this.
3939		 * JRA.
3940		 */
3941		if (!send_keepalive(smbd_server_fd())) {
3942			exit_server_cleanly("reply_writebraw: send of "
3943				"keepalive failed");
3944		}
3945#endif
3946		TALLOC_FREE(req->outbuf);
3947	}
3948	return;
3949
3950strict_unlock:
3951	SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
3952
3953	END_PROFILE(SMBwritebraw);
3954	return;
3955}
3956
3957#undef DBGC_CLASS
3958#define DBGC_CLASS DBGC_LOCKING
3959
3960/****************************************************************************
3961 Reply to a writeunlock (core+).
3962****************************************************************************/
3963
3964void reply_writeunlock(struct smb_request *req)
3965{
3966	connection_struct *conn = req->conn;
3967	ssize_t nwritten = -1;
3968	size_t numtowrite;
3969	SMB_OFF_T startpos;
3970	const char *data;
3971	NTSTATUS status = NT_STATUS_OK;
3972	files_struct *fsp;
3973	struct lock_struct lock;
3974	int saved_errno = 0;
3975
3976	START_PROFILE(SMBwriteunlock);
3977
3978	if (req->wct < 5) {
3979		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3980		END_PROFILE(SMBwriteunlock);
3981		return;
3982	}
3983
3984	fsp = file_fsp(req, SVAL(req->vwv+0, 0));
3985
3986	if (!check_fsp(conn, req, fsp)) {
3987		END_PROFILE(SMBwriteunlock);
3988		return;
3989	}
3990
3991	if (!CHECK_WRITE(fsp)) {
3992		reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3993		END_PROFILE(SMBwriteunlock);
3994		return;
3995	}
3996
3997	numtowrite = SVAL(req->vwv+1, 0);
3998	startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
3999	data = (const char *)req->buf + 3;
4000
4001	if (numtowrite) {
4002		init_strict_lock_struct(fsp, (uint32)req->smbpid,
4003		    (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4004		    &lock);
4005
4006		if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4007			reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4008			END_PROFILE(SMBwriteunlock);
4009			return;
4010		}
4011	}
4012
4013	/* The special X/Open SMB protocol handling of
4014	   zero length writes is *NOT* done for
4015	   this call */
4016	if(numtowrite == 0) {
4017		nwritten = 0;
4018	} else {
4019		nwritten = write_file(req,fsp,data,startpos,numtowrite);
4020		saved_errno = errno;
4021	}
4022
4023	status = sync_file(conn, fsp, False /* write through */);
4024	if (!NT_STATUS_IS_OK(status)) {
4025		DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
4026			 fsp_str_dbg(fsp), nt_errstr(status)));
4027		reply_nterror(req, status);
4028		goto strict_unlock;
4029	}
4030
4031	if(nwritten < 0) {
4032		reply_nterror(req, map_nt_error_from_unix(saved_errno));
4033		goto strict_unlock;
4034	}
4035
4036	if((nwritten < numtowrite) && (numtowrite != 0)) {
4037		reply_nterror(req, NT_STATUS_DISK_FULL);
4038		goto strict_unlock;
4039	}
4040
4041	if (numtowrite) {
4042		status = do_unlock(smbd_messaging_context(),
4043				fsp,
4044				req->smbpid,
4045				(uint64_t)numtowrite,
4046				(uint64_t)startpos,
4047				WINDOWS_LOCK);
4048
4049		if (NT_STATUS_V(status)) {
4050			reply_nterror(req, status);
4051			goto strict_unlock;
4052		}
4053	}
4054
4055	reply_outbuf(req, 1, 0);
4056
4057	SSVAL(req->outbuf,smb_vwv0,nwritten);
4058
4059	DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
4060		 fsp->fnum, (int)numtowrite, (int)nwritten));
4061
4062strict_unlock:
4063	if (numtowrite) {
4064		SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4065	}
4066
4067	END_PROFILE(SMBwriteunlock);
4068	return;
4069}
4070
4071#undef DBGC_CLASS
4072#define DBGC_CLASS DBGC_ALL
4073
4074/****************************************************************************
4075 Reply to a write.
4076****************************************************************************/
4077
4078void reply_write(struct smb_request *req)
4079{
4080	connection_struct *conn = req->conn;
4081	size_t numtowrite;
4082	ssize_t nwritten = -1;
4083	SMB_OFF_T startpos;
4084	const char *data;
4085	files_struct *fsp;
4086	struct lock_struct lock;
4087	NTSTATUS status;
4088	int saved_errno = 0;
4089
4090	START_PROFILE(SMBwrite);
4091
4092	if (req->wct < 5) {
4093		END_PROFILE(SMBwrite);
4094		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4095		return;
4096	}
4097
4098	/* If it's an IPC, pass off the pipe handler. */
4099	if (IS_IPC(conn)) {
4100		reply_pipe_write(req);
4101		END_PROFILE(SMBwrite);
4102		return;
4103	}
4104
4105	fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4106
4107	if (!check_fsp(conn, req, fsp)) {
4108		END_PROFILE(SMBwrite);
4109		return;
4110	}
4111
4112	if (!CHECK_WRITE(fsp)) {
4113		reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4114		END_PROFILE(SMBwrite);
4115		return;
4116	}
4117
4118	numtowrite = SVAL(req->vwv+1, 0);
4119	startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4120	data = (const char *)req->buf + 3;
4121
4122	init_strict_lock_struct(fsp, (uint32)req->smbpid,
4123	    (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4124	    &lock);
4125
4126	if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4127		reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4128		END_PROFILE(SMBwrite);
4129		return;
4130	}
4131
4132	/*
4133	 * X/Open SMB protocol says that if smb_vwv1 is
4134	 * zero then the file size should be extended or
4135	 * truncated to the size given in smb_vwv[2-3].
4136	 */
4137
4138	if(numtowrite == 0) {
4139		/*
4140		 * This is actually an allocate call, and set EOF. JRA.
4141		 */
4142		nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
4143		if (nwritten < 0) {
4144			reply_nterror(req, NT_STATUS_DISK_FULL);
4145			goto strict_unlock;
4146		}
4147		nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
4148		if (nwritten < 0) {
4149			reply_nterror(req, NT_STATUS_DISK_FULL);
4150			goto strict_unlock;
4151		}
4152		trigger_write_time_update_immediate(fsp);
4153	} else {
4154		nwritten = write_file(req,fsp,data,startpos,numtowrite);
4155	}
4156
4157	status = sync_file(conn, fsp, False);
4158	if (!NT_STATUS_IS_OK(status)) {
4159		DEBUG(5,("reply_write: sync_file for %s returned %s\n",
4160			 fsp_str_dbg(fsp), nt_errstr(status)));
4161		reply_nterror(req, status);
4162		goto strict_unlock;
4163	}
4164
4165	if(nwritten < 0) {
4166		reply_nterror(req, map_nt_error_from_unix(saved_errno));
4167		goto strict_unlock;
4168	}
4169
4170	if((nwritten == 0) && (numtowrite != 0)) {
4171		reply_nterror(req, NT_STATUS_DISK_FULL);
4172		goto strict_unlock;
4173	}
4174
4175	reply_outbuf(req, 1, 0);
4176
4177	SSVAL(req->outbuf,smb_vwv0,nwritten);
4178
4179	if (nwritten < (ssize_t)numtowrite) {
4180		SCVAL(req->outbuf,smb_rcls,ERRHRD);
4181		SSVAL(req->outbuf,smb_err,ERRdiskfull);
4182	}
4183
4184	DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
4185
4186strict_unlock:
4187	SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4188
4189	END_PROFILE(SMBwrite);
4190	return;
4191}
4192
4193/****************************************************************************
4194 Ensure a buffer is a valid writeX for recvfile purposes.
4195****************************************************************************/
4196
4197#define STANDARD_WRITE_AND_X_HEADER_SIZE (smb_size - 4 + /* basic header */ \
4198						(2*14) + /* word count (including bcc) */ \
4199						1 /* pad byte */)
4200
4201bool is_valid_writeX_buffer(const uint8_t *inbuf)
4202{
4203	size_t numtowrite;
4204	connection_struct *conn = NULL;
4205	unsigned int doff = 0;
4206	size_t len = smb_len_large(inbuf);
4207	struct smbd_server_connection *sconn = smbd_server_conn;
4208
4209	if (is_encrypted_packet(inbuf)) {
4210		/* Can't do this on encrypted
4211		 * connections. */
4212		return false;
4213	}
4214
4215	if (CVAL(inbuf,smb_com) != SMBwriteX) {
4216		return false;
4217	}
4218
4219	if (CVAL(inbuf,smb_vwv0) != 0xFF ||
4220			CVAL(inbuf,smb_wct) != 14) {
4221		DEBUG(10,("is_valid_writeX_buffer: chained or "
4222			"invalid word length.\n"));
4223		return false;
4224	}
4225
4226	conn = conn_find(sconn, SVAL(inbuf, smb_tid));
4227	if (conn == NULL) {
4228		DEBUG(10,("is_valid_writeX_buffer: bad tid\n"));
4229		return false;
4230	}
4231	if (IS_IPC(conn)) {
4232		DEBUG(10,("is_valid_writeX_buffer: IPC$ tid\n"));
4233		return false;
4234	}
4235	if (IS_PRINT(conn)) {
4236		DEBUG(10,("is_valid_writeX_buffer: printing tid\n"));
4237		return false;
4238	}
4239	doff = SVAL(inbuf,smb_vwv11);
4240
4241	numtowrite = SVAL(inbuf,smb_vwv10);
4242
4243	if (len > doff && len - doff > 0xFFFF) {
4244		numtowrite |= (((size_t)SVAL(inbuf,smb_vwv9))<<16);
4245	}
4246
4247	if (numtowrite == 0) {
4248		DEBUG(10,("is_valid_writeX_buffer: zero write\n"));
4249		return false;
4250	}
4251
4252	/* Ensure the sizes match up. */
4253	if (doff < STANDARD_WRITE_AND_X_HEADER_SIZE) {
4254		/* no pad byte...old smbclient :-( */
4255		DEBUG(10,("is_valid_writeX_buffer: small doff %u (min %u)\n",
4256			(unsigned int)doff,
4257			(unsigned int)STANDARD_WRITE_AND_X_HEADER_SIZE));
4258		return false;
4259	}
4260
4261	if (len - doff != numtowrite) {
4262		DEBUG(10,("is_valid_writeX_buffer: doff mismatch "
4263			"len = %u, doff = %u, numtowrite = %u\n",
4264			(unsigned int)len,
4265			(unsigned int)doff,
4266			(unsigned int)numtowrite ));
4267		return false;
4268	}
4269
4270	DEBUG(10,("is_valid_writeX_buffer: true "
4271		"len = %u, doff = %u, numtowrite = %u\n",
4272		(unsigned int)len,
4273		(unsigned int)doff,
4274		(unsigned int)numtowrite ));
4275
4276	return true;
4277}
4278
4279/****************************************************************************
4280 Reply to a write and X.
4281****************************************************************************/
4282
4283void reply_write_and_X(struct smb_request *req)
4284{
4285	connection_struct *conn = req->conn;
4286	files_struct *fsp;
4287	struct lock_struct lock;
4288	SMB_OFF_T startpos;
4289	size_t numtowrite;
4290	bool write_through;
4291	ssize_t nwritten;
4292	unsigned int smb_doff;
4293	unsigned int smblen;
4294	char *data;
4295	NTSTATUS status;
4296
4297	START_PROFILE(SMBwriteX);
4298
4299	if ((req->wct != 12) && (req->wct != 14)) {
4300		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4301		END_PROFILE(SMBwriteX);
4302		return;
4303	}
4304
4305	numtowrite = SVAL(req->vwv+10, 0);
4306	smb_doff = SVAL(req->vwv+11, 0);
4307	smblen = smb_len(req->inbuf);
4308
4309	if (req->unread_bytes > 0xFFFF ||
4310			(smblen > smb_doff &&
4311				smblen - smb_doff > 0xFFFF)) {
4312		numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
4313	}
4314
4315	if (req->unread_bytes) {
4316		/* Can't do a recvfile write on IPC$ */
4317		if (IS_IPC(conn)) {
4318			reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4319			END_PROFILE(SMBwriteX);
4320			return;
4321		}
4322	       	if (numtowrite != req->unread_bytes) {
4323			reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4324			END_PROFILE(SMBwriteX);
4325			return;
4326		}
4327	} else {
4328		if (smb_doff > smblen || smb_doff + numtowrite < numtowrite ||
4329				smb_doff + numtowrite > smblen) {
4330			reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4331			END_PROFILE(SMBwriteX);
4332			return;
4333		}
4334	}
4335
4336	/* If it's an IPC, pass off the pipe handler. */
4337	if (IS_IPC(conn)) {
4338		if (req->unread_bytes) {
4339			reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4340			END_PROFILE(SMBwriteX);
4341			return;
4342		}
4343		reply_pipe_write_and_X(req);
4344		END_PROFILE(SMBwriteX);
4345		return;
4346	}
4347
4348	fsp = file_fsp(req, SVAL(req->vwv+2, 0));
4349	startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
4350	write_through = BITSETW(req->vwv+7,0);
4351
4352	if (!check_fsp(conn, req, fsp)) {
4353		END_PROFILE(SMBwriteX);
4354		return;
4355	}
4356
4357	if (!CHECK_WRITE(fsp)) {
4358		reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4359		END_PROFILE(SMBwriteX);
4360		return;
4361	}
4362
4363	data = smb_base(req->inbuf) + smb_doff;
4364
4365	if(req->wct == 14) {
4366#ifdef LARGE_SMB_OFF_T
4367		/*
4368		 * This is a large offset (64 bit) write.
4369		 */
4370		startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
4371
4372#else /* !LARGE_SMB_OFF_T */
4373
4374		/*
4375		 * Ensure we haven't been sent a >32 bit offset.
4376		 */
4377
4378		if(IVAL(req->vwv+12, 0) != 0) {
4379			DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
4380				 "used and we don't support 64 bit offsets.\n",
4381				 (unsigned int)IVAL(req->vwv+12, 0) ));
4382			reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4383			END_PROFILE(SMBwriteX);
4384			return;
4385		}
4386
4387#endif /* LARGE_SMB_OFF_T */
4388	}
4389
4390	init_strict_lock_struct(fsp, (uint32)req->smbpid,
4391	    (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4392	    &lock);
4393
4394	if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4395		reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4396		END_PROFILE(SMBwriteX);
4397		return;
4398	}
4399
4400	/* X/Open SMB protocol says that, unlike SMBwrite
4401	if the length is zero then NO truncation is
4402	done, just a write of zero. To truncate a file,
4403	use SMBwrite. */
4404
4405	if(numtowrite == 0) {
4406		nwritten = 0;
4407	} else {
4408
4409		if ((req->unread_bytes == 0) &&
4410		    schedule_aio_write_and_X(conn, req, fsp, data, startpos,
4411					     numtowrite)) {
4412			goto strict_unlock;
4413		}
4414
4415		nwritten = write_file(req,fsp,data,startpos,numtowrite);
4416	}
4417
4418	if(nwritten < 0) {
4419		reply_nterror(req, map_nt_error_from_unix(errno));
4420		goto strict_unlock;
4421	}
4422
4423	if((nwritten == 0) && (numtowrite != 0)) {
4424		reply_nterror(req, NT_STATUS_DISK_FULL);
4425		goto strict_unlock;
4426	}
4427
4428	reply_outbuf(req, 6, 0);
4429	SSVAL(req->outbuf,smb_vwv2,nwritten);
4430	SSVAL(req->outbuf,smb_vwv4,nwritten>>16);
4431
4432	if (nwritten < (ssize_t)numtowrite) {
4433		SCVAL(req->outbuf,smb_rcls,ERRHRD);
4434		SSVAL(req->outbuf,smb_err,ERRdiskfull);
4435	}
4436
4437	DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
4438		fsp->fnum, (int)numtowrite, (int)nwritten));
4439
4440	status = sync_file(conn, fsp, write_through);
4441	if (!NT_STATUS_IS_OK(status)) {
4442		DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
4443			 fsp_str_dbg(fsp), nt_errstr(status)));
4444		reply_nterror(req, status);
4445		goto strict_unlock;
4446	}
4447
4448	SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4449
4450	END_PROFILE(SMBwriteX);
4451	chain_reply(req);
4452	return;
4453
4454strict_unlock:
4455	SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4456
4457	END_PROFILE(SMBwriteX);
4458	return;
4459}
4460
4461/****************************************************************************
4462 Reply to a lseek.
4463****************************************************************************/
4464
4465void reply_lseek(struct smb_request *req)
4466{
4467	connection_struct *conn = req->conn;
4468	SMB_OFF_T startpos;
4469	SMB_OFF_T res= -1;
4470	int mode,umode;
4471	files_struct *fsp;
4472
4473	START_PROFILE(SMBlseek);
4474
4475	if (req->wct < 4) {
4476		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4477		END_PROFILE(SMBlseek);
4478		return;
4479	}
4480
4481	fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4482
4483	if (!check_fsp(conn, req, fsp)) {
4484		return;
4485	}
4486
4487	flush_write_cache(fsp, SEEK_FLUSH);
4488
4489	mode = SVAL(req->vwv+1, 0) & 3;
4490	/* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
4491	startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
4492
4493	switch (mode) {
4494		case 0:
4495			umode = SEEK_SET;
4496			res = startpos;
4497			break;
4498		case 1:
4499			umode = SEEK_CUR;
4500			res = fsp->fh->pos + startpos;
4501			break;
4502		case 2:
4503			umode = SEEK_END;
4504			break;
4505		default:
4506			umode = SEEK_SET;
4507			res = startpos;
4508			break;
4509	}
4510
4511	if (umode == SEEK_END) {
4512		if((res = SMB_VFS_LSEEK(fsp,startpos,umode)) == -1) {
4513			if(errno == EINVAL) {
4514				SMB_OFF_T current_pos = startpos;
4515
4516				if(fsp_stat(fsp) == -1) {
4517					reply_nterror(req,
4518						map_nt_error_from_unix(errno));
4519					END_PROFILE(SMBlseek);
4520					return;
4521				}
4522
4523				current_pos += fsp->fsp_name->st.st_ex_size;
4524				if(current_pos < 0)
4525					res = SMB_VFS_LSEEK(fsp,0,SEEK_SET);
4526			}
4527		}
4528
4529		if(res == -1) {
4530			reply_nterror(req, map_nt_error_from_unix(errno));
4531			END_PROFILE(SMBlseek);
4532			return;
4533		}
4534	}
4535
4536	fsp->fh->pos = res;
4537
4538	reply_outbuf(req, 2, 0);
4539	SIVAL(req->outbuf,smb_vwv0,res);
4540
4541	DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
4542		fsp->fnum, (double)startpos, (double)res, mode));
4543
4544	END_PROFILE(SMBlseek);
4545	return;
4546}
4547
4548/****************************************************************************
4549 Reply to a flush.
4550****************************************************************************/
4551
4552void reply_flush(struct smb_request *req)
4553{
4554	connection_struct *conn = req->conn;
4555	uint16 fnum;
4556	files_struct *fsp;
4557
4558	START_PROFILE(SMBflush);
4559
4560	if (req->wct < 1) {
4561		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4562		return;
4563	}
4564
4565	fnum = SVAL(req->vwv+0, 0);
4566	fsp = file_fsp(req, fnum);
4567
4568	if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
4569		return;
4570	}
4571
4572	if (!fsp) {
4573		file_sync_all(conn);
4574	} else {
4575		NTSTATUS status = sync_file(conn, fsp, True);
4576		if (!NT_STATUS_IS_OK(status)) {
4577			DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
4578				fsp_str_dbg(fsp), nt_errstr(status)));
4579			reply_nterror(req, status);
4580			END_PROFILE(SMBflush);
4581			return;
4582		}
4583	}
4584
4585	reply_outbuf(req, 0, 0);
4586
4587	DEBUG(3,("flush\n"));
4588	END_PROFILE(SMBflush);
4589	return;
4590}
4591
4592/****************************************************************************
4593 Reply to a exit.
4594 conn POINTER CAN BE NULL HERE !
4595****************************************************************************/
4596
4597void reply_exit(struct smb_request *req)
4598{
4599	START_PROFILE(SMBexit);
4600
4601	file_close_pid(req->smbpid, req->vuid);
4602
4603	reply_outbuf(req, 0, 0);
4604
4605	DEBUG(3,("exit\n"));
4606
4607	END_PROFILE(SMBexit);
4608	return;
4609}
4610
4611/****************************************************************************
4612 Reply to a close - has to deal with closing a directory opened by NT SMB's.
4613****************************************************************************/
4614
4615void reply_close(struct smb_request *req)
4616{
4617	connection_struct *conn = req->conn;
4618	NTSTATUS status = NT_STATUS_OK;
4619	files_struct *fsp = NULL;
4620	START_PROFILE(SMBclose);
4621
4622	if (req->wct < 3) {
4623		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4624		END_PROFILE(SMBclose);
4625		return;
4626	}
4627
4628	fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4629
4630	/*
4631	 * We can only use check_fsp if we know it's not a directory.
4632	 */
4633
4634	if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
4635		reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4636		END_PROFILE(SMBclose);
4637		return;
4638	}
4639
4640	if(fsp->is_directory) {
4641		/*
4642		 * Special case - close NT SMB directory handle.
4643		 */
4644		DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
4645		status = close_file(req, fsp, NORMAL_CLOSE);
4646	} else {
4647		time_t t;
4648		/*
4649		 * Close ordinary file.
4650		 */
4651
4652		DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
4653			 fsp->fh->fd, fsp->fnum,
4654			 conn->num_files_open));
4655
4656		/*
4657		 * Take care of any time sent in the close.
4658		 */
4659
4660		t = srv_make_unix_date3(req->vwv+1);
4661		set_close_write_time(fsp, convert_time_t_to_timespec(t));
4662
4663		/*
4664		 * close_file() returns the unix errno if an error
4665		 * was detected on close - normally this is due to
4666		 * a disk full error. If not then it was probably an I/O error.
4667		 */
4668
4669		status = close_file(req, fsp, NORMAL_CLOSE);
4670	}
4671
4672	if (!NT_STATUS_IS_OK(status)) {
4673		reply_nterror(req, status);
4674		END_PROFILE(SMBclose);
4675		return;
4676	}
4677
4678	reply_outbuf(req, 0, 0);
4679	END_PROFILE(SMBclose);
4680	return;
4681}
4682
4683/****************************************************************************
4684 Reply to a writeclose (Core+ protocol).
4685****************************************************************************/
4686
4687void reply_writeclose(struct smb_request *req)
4688{
4689	connection_struct *conn = req->conn;
4690	size_t numtowrite;
4691	ssize_t nwritten = -1;
4692	NTSTATUS close_status = NT_STATUS_OK;
4693	SMB_OFF_T startpos;
4694	const char *data;
4695	struct timespec mtime;
4696	files_struct *fsp;
4697	struct lock_struct lock;
4698
4699	START_PROFILE(SMBwriteclose);
4700
4701	if (req->wct < 6) {
4702		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4703		END_PROFILE(SMBwriteclose);
4704		return;
4705	}
4706
4707	fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4708
4709	if (!check_fsp(conn, req, fsp)) {
4710		END_PROFILE(SMBwriteclose);
4711		return;
4712	}
4713	if (!CHECK_WRITE(fsp)) {
4714		reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4715		END_PROFILE(SMBwriteclose);
4716		return;
4717	}
4718
4719	numtowrite = SVAL(req->vwv+1, 0);
4720	startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
4721	mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
4722	data = (const char *)req->buf + 1;
4723
4724	if (numtowrite) {
4725		init_strict_lock_struct(fsp, (uint32)req->smbpid,
4726		    (uint64_t)startpos, (uint64_t)numtowrite, WRITE_LOCK,
4727		    &lock);
4728
4729		if (!SMB_VFS_STRICT_LOCK(conn, fsp, &lock)) {
4730			reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
4731			END_PROFILE(SMBwriteclose);
4732			return;
4733		}
4734	}
4735
4736	nwritten = write_file(req,fsp,data,startpos,numtowrite);
4737
4738	set_close_write_time(fsp, mtime);
4739
4740	/*
4741	 * More insanity. W2K only closes the file if writelen > 0.
4742	 * JRA.
4743	 */
4744
4745	if (numtowrite) {
4746		DEBUG(3,("reply_writeclose: zero length write doesn't close "
4747			 "file %s\n", fsp_str_dbg(fsp)));
4748		close_status = close_file(req, fsp, NORMAL_CLOSE);
4749	}
4750
4751	DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
4752		 fsp->fnum, (int)numtowrite, (int)nwritten,
4753		 conn->num_files_open));
4754
4755	if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
4756		reply_nterror(req, NT_STATUS_DISK_FULL);
4757		goto strict_unlock;
4758	}
4759
4760	if(!NT_STATUS_IS_OK(close_status)) {
4761		reply_nterror(req, close_status);
4762		goto strict_unlock;
4763	}
4764
4765	reply_outbuf(req, 1, 0);
4766
4767	SSVAL(req->outbuf,smb_vwv0,nwritten);
4768
4769strict_unlock:
4770	if (numtowrite) {
4771		SMB_VFS_STRICT_UNLOCK(conn, fsp, &lock);
4772	}
4773
4774	END_PROFILE(SMBwriteclose);
4775	return;
4776}
4777
4778#undef DBGC_CLASS
4779#define DBGC_CLASS DBGC_LOCKING
4780
4781/****************************************************************************
4782 Reply to a lock.
4783****************************************************************************/
4784
4785void reply_lock(struct smb_request *req)
4786{
4787	connection_struct *conn = req->conn;
4788	uint64_t count,offset;
4789	NTSTATUS status;
4790	files_struct *fsp;
4791	struct byte_range_lock *br_lck = NULL;
4792
4793	START_PROFILE(SMBlock);
4794
4795	if (req->wct < 5) {
4796		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4797		END_PROFILE(SMBlock);
4798		return;
4799	}
4800
4801	fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4802
4803	if (!check_fsp(conn, req, fsp)) {
4804		END_PROFILE(SMBlock);
4805		return;
4806	}
4807
4808	count = (uint64_t)IVAL(req->vwv+1, 0);
4809	offset = (uint64_t)IVAL(req->vwv+3, 0);
4810
4811	DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4812		 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
4813
4814	br_lck = do_lock(smbd_messaging_context(),
4815			fsp,
4816			req->smbpid,
4817			count,
4818			offset,
4819			WRITE_LOCK,
4820			WINDOWS_LOCK,
4821			False, /* Non-blocking lock. */
4822			&status,
4823			NULL,
4824			NULL);
4825
4826	TALLOC_FREE(br_lck);
4827
4828	if (NT_STATUS_V(status)) {
4829		reply_nterror(req, status);
4830		END_PROFILE(SMBlock);
4831		return;
4832	}
4833
4834	reply_outbuf(req, 0, 0);
4835
4836	END_PROFILE(SMBlock);
4837	return;
4838}
4839
4840/****************************************************************************
4841 Reply to a unlock.
4842****************************************************************************/
4843
4844void reply_unlock(struct smb_request *req)
4845{
4846	connection_struct *conn = req->conn;
4847	uint64_t count,offset;
4848	NTSTATUS status;
4849	files_struct *fsp;
4850
4851	START_PROFILE(SMBunlock);
4852
4853	if (req->wct < 5) {
4854		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4855		END_PROFILE(SMBunlock);
4856		return;
4857	}
4858
4859	fsp = file_fsp(req, SVAL(req->vwv+0, 0));
4860
4861	if (!check_fsp(conn, req, fsp)) {
4862		END_PROFILE(SMBunlock);
4863		return;
4864	}
4865
4866	count = (uint64_t)IVAL(req->vwv+1, 0);
4867	offset = (uint64_t)IVAL(req->vwv+3, 0);
4868
4869	status = do_unlock(smbd_messaging_context(),
4870			fsp,
4871			req->smbpid,
4872			count,
4873			offset,
4874			WINDOWS_LOCK);
4875
4876	if (NT_STATUS_V(status)) {
4877		reply_nterror(req, status);
4878		END_PROFILE(SMBunlock);
4879		return;
4880	}
4881
4882	DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
4883		    fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
4884
4885	reply_outbuf(req, 0, 0);
4886
4887	END_PROFILE(SMBunlock);
4888	return;
4889}
4890
4891#undef DBGC_CLASS
4892#define DBGC_CLASS DBGC_ALL
4893
4894/****************************************************************************
4895 Reply to a tdis.
4896 conn POINTER CAN BE NULL HERE !
4897****************************************************************************/
4898
4899void reply_tdis(struct smb_request *req)
4900{
4901	connection_struct *conn = req->conn;
4902	START_PROFILE(SMBtdis);
4903
4904	if (!conn) {
4905		DEBUG(4,("Invalid connection in tdis\n"));
4906		reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
4907		END_PROFILE(SMBtdis);
4908		return;
4909	}
4910
4911	conn->used = False;
4912
4913	close_cnum(conn,req->vuid);
4914	req->conn = NULL;
4915
4916	reply_outbuf(req, 0, 0);
4917	END_PROFILE(SMBtdis);
4918	return;
4919}
4920
4921/****************************************************************************
4922 Reply to a echo.
4923 conn POINTER CAN BE NULL HERE !
4924****************************************************************************/
4925
4926void reply_echo(struct smb_request *req)
4927{
4928	connection_struct *conn = req->conn;
4929	struct smb_perfcount_data local_pcd;
4930	struct smb_perfcount_data *cur_pcd;
4931	int smb_reverb;
4932	int seq_num;
4933
4934	START_PROFILE(SMBecho);
4935
4936	smb_init_perfcount_data(&local_pcd);
4937
4938	if (req->wct < 1) {
4939		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4940		END_PROFILE(SMBecho);
4941		return;
4942	}
4943
4944	smb_reverb = SVAL(req->vwv+0, 0);
4945
4946	reply_outbuf(req, 1, req->buflen);
4947
4948	/* copy any incoming data back out */
4949	if (req->buflen > 0) {
4950		memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
4951	}
4952
4953	if (smb_reverb > 100) {
4954		DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
4955		smb_reverb = 100;
4956	}
4957
4958	for (seq_num = 1 ; seq_num <= smb_reverb ; seq_num++) {
4959
4960		/* this makes sure we catch the request pcd */
4961		if (seq_num == smb_reverb) {
4962			cur_pcd = &req->pcd;
4963		} else {
4964			SMB_PERFCOUNT_COPY_CONTEXT(&req->pcd, &local_pcd);
4965			cur_pcd = &local_pcd;
4966		}
4967
4968		SSVAL(req->outbuf,smb_vwv0,seq_num);
4969
4970		show_msg((char *)req->outbuf);
4971		if (!srv_send_smb(smbd_server_fd(),
4972				(char *)req->outbuf,
4973				true, req->seqnum+1,
4974				IS_CONN_ENCRYPTED(conn)||req->encrypted,
4975				cur_pcd))
4976			exit_server_cleanly("reply_echo: srv_send_smb failed.");
4977	}
4978
4979	DEBUG(3,("echo %d times\n", smb_reverb));
4980
4981	TALLOC_FREE(req->outbuf);
4982
4983	END_PROFILE(SMBecho);
4984	return;
4985}
4986
4987/****************************************************************************
4988 Reply to a printopen.
4989****************************************************************************/
4990
4991void reply_printopen(struct smb_request *req)
4992{
4993	connection_struct *conn = req->conn;
4994	files_struct *fsp;
4995	NTSTATUS status;
4996
4997	START_PROFILE(SMBsplopen);
4998
4999	if (req->wct < 2) {
5000		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5001		END_PROFILE(SMBsplopen);
5002		return;
5003	}
5004
5005	if (!CAN_PRINT(conn)) {
5006		reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5007		END_PROFILE(SMBsplopen);
5008		return;
5009	}
5010
5011	status = file_new(req, conn, &fsp);
5012	if(!NT_STATUS_IS_OK(status)) {
5013		reply_nterror(req, status);
5014		END_PROFILE(SMBsplopen);
5015		return;
5016	}
5017
5018	/* Open for exclusive use, write only. */
5019	status = print_fsp_open(req, conn, NULL, req->vuid, fsp);
5020
5021	if (!NT_STATUS_IS_OK(status)) {
5022		file_free(req, fsp);
5023		reply_nterror(req, status);
5024		END_PROFILE(SMBsplopen);
5025		return;
5026	}
5027
5028	reply_outbuf(req, 1, 0);
5029	SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
5030
5031	DEBUG(3,("openprint fd=%d fnum=%d\n",
5032		 fsp->fh->fd, fsp->fnum));
5033
5034	END_PROFILE(SMBsplopen);
5035	return;
5036}
5037
5038/****************************************************************************
5039 Reply to a printclose.
5040****************************************************************************/
5041
5042void reply_printclose(struct smb_request *req)
5043{
5044	connection_struct *conn = req->conn;
5045	files_struct *fsp;
5046	NTSTATUS status;
5047
5048	START_PROFILE(SMBsplclose);
5049
5050	if (req->wct < 1) {
5051		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5052		END_PROFILE(SMBsplclose);
5053		return;
5054	}
5055
5056	fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5057
5058	if (!check_fsp(conn, req, fsp)) {
5059		END_PROFILE(SMBsplclose);
5060                return;
5061        }
5062
5063	if (!CAN_PRINT(conn)) {
5064		reply_force_doserror(req, ERRSRV, ERRerror);
5065		END_PROFILE(SMBsplclose);
5066		return;
5067	}
5068
5069	DEBUG(3,("printclose fd=%d fnum=%d\n",
5070		 fsp->fh->fd,fsp->fnum));
5071
5072	status = close_file(req, fsp, NORMAL_CLOSE);
5073
5074	if(!NT_STATUS_IS_OK(status)) {
5075		reply_nterror(req, status);
5076		END_PROFILE(SMBsplclose);
5077		return;
5078	}
5079
5080	reply_outbuf(req, 0, 0);
5081
5082	END_PROFILE(SMBsplclose);
5083	return;
5084}
5085
5086/****************************************************************************
5087 Reply to a printqueue.
5088****************************************************************************/
5089
5090void reply_printqueue(struct smb_request *req)
5091{
5092	connection_struct *conn = req->conn;
5093	int max_count;
5094	int start_index;
5095
5096	START_PROFILE(SMBsplretq);
5097
5098	if (req->wct < 2) {
5099		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5100		END_PROFILE(SMBsplretq);
5101		return;
5102	}
5103
5104	max_count = SVAL(req->vwv+0, 0);
5105	start_index = SVAL(req->vwv+1, 0);
5106
5107	/* we used to allow the client to get the cnum wrong, but that
5108	   is really quite gross and only worked when there was only
5109	   one printer - I think we should now only accept it if they
5110	   get it right (tridge) */
5111	if (!CAN_PRINT(conn)) {
5112		reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5113		END_PROFILE(SMBsplretq);
5114		return;
5115	}
5116
5117	reply_outbuf(req, 2, 3);
5118	SSVAL(req->outbuf,smb_vwv0,0);
5119	SSVAL(req->outbuf,smb_vwv1,0);
5120	SCVAL(smb_buf(req->outbuf),0,1);
5121	SSVAL(smb_buf(req->outbuf),1,0);
5122
5123	DEBUG(3,("printqueue start_index=%d max_count=%d\n",
5124		 start_index, max_count));
5125
5126	{
5127		print_queue_struct *queue = NULL;
5128		print_status_struct status;
5129		int count = print_queue_status(SNUM(conn), &queue, &status);
5130		int num_to_get = ABS(max_count);
5131		int first = (max_count>0?start_index:start_index+max_count+1);
5132		int i;
5133
5134		if (first >= count)
5135			num_to_get = 0;
5136		else
5137			num_to_get = MIN(num_to_get,count-first);
5138
5139
5140		for (i=first;i<first+num_to_get;i++) {
5141			char blob[28];
5142			char *p = blob;
5143
5144			srv_put_dos_date2(p,0,queue[i].time);
5145			SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
5146			SSVAL(p,5, queue[i].job);
5147			SIVAL(p,7,queue[i].size);
5148			SCVAL(p,11,0);
5149			srvstr_push(blob, req->flags2, p+12,
5150				    queue[i].fs_user, 16, STR_ASCII);
5151
5152			if (message_push_blob(
5153				    &req->outbuf,
5154				    data_blob_const(
5155					    blob, sizeof(blob))) == -1) {
5156				reply_nterror(req, NT_STATUS_NO_MEMORY);
5157				END_PROFILE(SMBsplretq);
5158				return;
5159			}
5160		}
5161
5162		if (count > 0) {
5163			SSVAL(req->outbuf,smb_vwv0,count);
5164			SSVAL(req->outbuf,smb_vwv1,
5165			      (max_count>0?first+count:first-1));
5166			SCVAL(smb_buf(req->outbuf),0,1);
5167			SSVAL(smb_buf(req->outbuf),1,28*count);
5168		}
5169
5170		SAFE_FREE(queue);
5171
5172		DEBUG(3,("%d entries returned in queue\n",count));
5173	}
5174
5175	END_PROFILE(SMBsplretq);
5176	return;
5177}
5178
5179/****************************************************************************
5180 Reply to a printwrite.
5181****************************************************************************/
5182
5183void reply_printwrite(struct smb_request *req)
5184{
5185	connection_struct *conn = req->conn;
5186	int numtowrite;
5187	const char *data;
5188	files_struct *fsp;
5189
5190	START_PROFILE(SMBsplwr);
5191
5192	if (req->wct < 1) {
5193		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5194		END_PROFILE(SMBsplwr);
5195		return;
5196	}
5197
5198	fsp = file_fsp(req, SVAL(req->vwv+0, 0));
5199
5200	if (!check_fsp(conn, req, fsp)) {
5201		END_PROFILE(SMBsplwr);
5202                return;
5203        }
5204
5205	if (!CAN_PRINT(conn)) {
5206		reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5207		END_PROFILE(SMBsplwr);
5208		return;
5209	}
5210
5211	if (!CHECK_WRITE(fsp)) {
5212		reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5213		END_PROFILE(SMBsplwr);
5214		return;
5215	}
5216
5217	numtowrite = SVAL(req->buf, 1);
5218
5219	if (req->buflen < numtowrite + 3) {
5220		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5221		END_PROFILE(SMBsplwr);
5222		return;
5223	}
5224
5225	data = (const char *)req->buf + 3;
5226
5227	if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
5228		reply_nterror(req, map_nt_error_from_unix(errno));
5229		END_PROFILE(SMBsplwr);
5230		return;
5231	}
5232
5233	DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
5234
5235	END_PROFILE(SMBsplwr);
5236	return;
5237}
5238
5239/****************************************************************************
5240 Reply to a mkdir.
5241****************************************************************************/
5242
5243void reply_mkdir(struct smb_request *req)
5244{
5245	connection_struct *conn = req->conn;
5246	struct smb_filename *smb_dname = NULL;
5247	char *directory = NULL;
5248	NTSTATUS status;
5249	TALLOC_CTX *ctx = talloc_tos();
5250
5251	START_PROFILE(SMBmkdir);
5252
5253	srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5254			    STR_TERMINATE, &status);
5255	if (!NT_STATUS_IS_OK(status)) {
5256		reply_nterror(req, status);
5257		goto out;
5258	}
5259
5260	status = filename_convert(ctx, conn,
5261				 req->flags2 & FLAGS2_DFS_PATHNAMES,
5262				 directory,
5263				 0,
5264				 NULL,
5265				 &smb_dname);
5266	if (!NT_STATUS_IS_OK(status)) {
5267		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5268			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5269					ERRSRV, ERRbadpath);
5270			goto out;
5271		}
5272		reply_nterror(req, status);
5273		goto out;
5274	}
5275
5276	status = create_directory(conn, req, smb_dname);
5277
5278	DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
5279
5280	if (!NT_STATUS_IS_OK(status)) {
5281
5282		if (!use_nt_status()
5283		    && NT_STATUS_EQUAL(status,
5284				       NT_STATUS_OBJECT_NAME_COLLISION)) {
5285			/*
5286			 * Yes, in the DOS error code case we get a
5287			 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
5288			 * samba4 torture test.
5289			 */
5290			status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
5291		}
5292
5293		reply_nterror(req, status);
5294		goto out;
5295	}
5296
5297	reply_outbuf(req, 0, 0);
5298
5299	DEBUG(3, ("mkdir %s\n", smb_dname->base_name));
5300 out:
5301	TALLOC_FREE(smb_dname);
5302	END_PROFILE(SMBmkdir);
5303	return;
5304}
5305
5306/****************************************************************************
5307 Reply to a rmdir.
5308****************************************************************************/
5309
5310void reply_rmdir(struct smb_request *req)
5311{
5312	connection_struct *conn = req->conn;
5313	struct smb_filename *smb_dname = NULL;
5314	char *directory = NULL;
5315	NTSTATUS status;
5316	TALLOC_CTX *ctx = talloc_tos();
5317	files_struct *fsp = NULL;
5318	int info = 0;
5319	struct smbd_server_connection *sconn = smbd_server_conn;
5320
5321	START_PROFILE(SMBrmdir);
5322
5323	srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
5324			    STR_TERMINATE, &status);
5325	if (!NT_STATUS_IS_OK(status)) {
5326		reply_nterror(req, status);
5327		goto out;
5328	}
5329
5330	status = filename_convert(ctx, conn,
5331				 req->flags2 & FLAGS2_DFS_PATHNAMES,
5332				 directory,
5333				 0,
5334				 NULL,
5335				 &smb_dname);
5336	if (!NT_STATUS_IS_OK(status)) {
5337		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5338			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
5339					ERRSRV, ERRbadpath);
5340			goto out;
5341		}
5342		reply_nterror(req, status);
5343		goto out;
5344	}
5345
5346	if (is_ntfs_stream_smb_fname(smb_dname)) {
5347		reply_nterror(req, NT_STATUS_NOT_A_DIRECTORY);
5348		goto out;
5349	}
5350
5351	status = SMB_VFS_CREATE_FILE(
5352		conn,                                   /* conn */
5353		req,                                    /* req */
5354		0,                                      /* root_dir_fid */
5355		smb_dname,                              /* fname */
5356		DELETE_ACCESS,                          /* access_mask */
5357		(FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
5358			FILE_SHARE_DELETE),
5359		FILE_OPEN,                              /* create_disposition*/
5360		FILE_DIRECTORY_FILE,                    /* create_options */
5361		FILE_ATTRIBUTE_DIRECTORY,               /* file_attributes */
5362		0,                                      /* oplock_request */
5363		0,                                      /* allocation_size */
5364		NULL,                                   /* sd */
5365		NULL,                                   /* ea_list */
5366		&fsp,                                   /* result */
5367		&info);                                 /* pinfo */
5368
5369	if (!NT_STATUS_IS_OK(status)) {
5370		if (open_was_deferred(req->mid)) {
5371			/* We have re-scheduled this call. */
5372			goto out;
5373		}
5374		reply_nterror(req, status);
5375		goto out;
5376	}
5377
5378	status = can_set_delete_on_close(fsp, FILE_ATTRIBUTE_DIRECTORY);
5379	if (!NT_STATUS_IS_OK(status)) {
5380		close_file(req, fsp, ERROR_CLOSE);
5381		reply_nterror(req, status);
5382		goto out;
5383	}
5384
5385	if (!set_delete_on_close(fsp, true, &conn->server_info->utok)) {
5386		close_file(req, fsp, ERROR_CLOSE);
5387		reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5388		goto out;
5389	}
5390
5391	status = close_file(req, fsp, NORMAL_CLOSE);
5392	if (!NT_STATUS_IS_OK(status)) {
5393		reply_nterror(req, status);
5394	} else {
5395		reply_outbuf(req, 0, 0);
5396	}
5397
5398	dptr_closepath(sconn, smb_dname->base_name, req->smbpid);
5399
5400	DEBUG(3, ("rmdir %s\n", smb_fname_str_dbg(smb_dname)));
5401 out:
5402	TALLOC_FREE(smb_dname);
5403	END_PROFILE(SMBrmdir);
5404	return;
5405}
5406
5407/*******************************************************************
5408 Resolve wildcards in a filename rename.
5409********************************************************************/
5410
5411static bool resolve_wildcards(TALLOC_CTX *ctx,
5412				const char *name1,
5413				const char *name2,
5414				char **pp_newname)
5415{
5416	char *name2_copy = NULL;
5417	char *root1 = NULL;
5418	char *root2 = NULL;
5419	char *ext1 = NULL;
5420	char *ext2 = NULL;
5421	char *p,*p2, *pname1, *pname2;
5422
5423	name2_copy = talloc_strdup(ctx, name2);
5424	if (!name2_copy) {
5425		return False;
5426	}
5427
5428	pname1 = strrchr_m(name1,'/');
5429	pname2 = strrchr_m(name2_copy,'/');
5430
5431	if (!pname1 || !pname2) {
5432		return False;
5433	}
5434
5435	/* Truncate the copy of name2 at the last '/' */
5436	*pname2 = '\0';
5437
5438	/* Now go past the '/' */
5439	pname1++;
5440	pname2++;
5441
5442	root1 = talloc_strdup(ctx, pname1);
5443	root2 = talloc_strdup(ctx, pname2);
5444
5445	if (!root1 || !root2) {
5446		return False;
5447	}
5448
5449	p = strrchr_m(root1,'.');
5450	if (p) {
5451		*p = 0;
5452		ext1 = talloc_strdup(ctx, p+1);
5453	} else {
5454		ext1 = talloc_strdup(ctx, "");
5455	}
5456	p = strrchr_m(root2,'.');
5457	if (p) {
5458		*p = 0;
5459		ext2 = talloc_strdup(ctx, p+1);
5460	} else {
5461		ext2 = talloc_strdup(ctx, "");
5462	}
5463
5464	if (!ext1 || !ext2) {
5465		return False;
5466	}
5467
5468	p = root1;
5469	p2 = root2;
5470	while (*p2) {
5471		if (*p2 == '?') {
5472			/* Hmmm. Should this be mb-aware ? */
5473			*p2 = *p;
5474			p2++;
5475		} else if (*p2 == '*') {
5476			*p2 = '\0';
5477			root2 = talloc_asprintf(ctx, "%s%s",
5478						root2,
5479						p);
5480			if (!root2) {
5481				return False;
5482			}
5483			break;
5484		} else {
5485			p2++;
5486		}
5487		if (*p) {
5488			p++;
5489		}
5490	}
5491
5492	p = ext1;
5493	p2 = ext2;
5494	while (*p2) {
5495		if (*p2 == '?') {
5496			/* Hmmm. Should this be mb-aware ? */
5497			*p2 = *p;
5498			p2++;
5499		} else if (*p2 == '*') {
5500			*p2 = '\0';
5501			ext2 = talloc_asprintf(ctx, "%s%s",
5502						ext2,
5503						p);
5504			if (!ext2) {
5505				return False;
5506			}
5507			break;
5508		} else {
5509			p2++;
5510		}
5511		if (*p) {
5512			p++;
5513		}
5514	}
5515
5516	if (*ext2) {
5517		*pp_newname = talloc_asprintf(ctx, "%s/%s.%s",
5518				name2_copy,
5519				root2,
5520				ext2);
5521	} else {
5522		*pp_newname = talloc_asprintf(ctx, "%s/%s",
5523				name2_copy,
5524				root2);
5525	}
5526
5527	if (!*pp_newname) {
5528		return False;
5529	}
5530
5531	return True;
5532}
5533
5534/****************************************************************************
5535 Ensure open files have their names updated. Updated to notify other smbd's
5536 asynchronously.
5537****************************************************************************/
5538
5539static void rename_open_files(connection_struct *conn,
5540			      struct share_mode_lock *lck,
5541			      const struct smb_filename *smb_fname_dst)
5542{
5543	files_struct *fsp;
5544	bool did_rename = False;
5545	NTSTATUS status;
5546
5547	for(fsp = file_find_di_first(lck->id); fsp;
5548	    fsp = file_find_di_next(fsp)) {
5549		/* fsp_name is a relative path under the fsp. To change this for other
5550		   sharepaths we need to manipulate relative paths. */
5551		/* TODO - create the absolute path and manipulate the newname
5552		   relative to the sharepath. */
5553		if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
5554			continue;
5555		}
5556		DEBUG(10, ("rename_open_files: renaming file fnum %d "
5557			   "(file_id %s) from %s -> %s\n", fsp->fnum,
5558			   file_id_string_tos(&fsp->file_id), fsp_str_dbg(fsp),
5559			   smb_fname_str_dbg(smb_fname_dst)));
5560
5561		status = fsp_set_smb_fname(fsp, smb_fname_dst);
5562		if (NT_STATUS_IS_OK(status)) {
5563			did_rename = True;
5564		}
5565	}
5566
5567	if (!did_rename) {
5568		DEBUG(10, ("rename_open_files: no open files on file_id %s "
5569			   "for %s\n", file_id_string_tos(&lck->id),
5570			   smb_fname_str_dbg(smb_fname_dst)));
5571	}
5572
5573	/* Send messages to all smbd's (not ourself) that the name has changed. */
5574	rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
5575			      smb_fname_dst);
5576
5577}
5578
5579/****************************************************************************
5580 We need to check if the source path is a parent directory of the destination
5581 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
5582 refuse the rename with a sharing violation. Under UNIX the above call can
5583 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
5584 probably need to check that the client is a Windows one before disallowing
5585 this as a UNIX client (one with UNIX extensions) can know the source is a
5586 symlink and make this decision intelligently. Found by an excellent bug
5587 report from <AndyLiebman@aol.com>.
5588****************************************************************************/
5589
5590static bool rename_path_prefix_equal(const struct smb_filename *smb_fname_src,
5591				     const struct smb_filename *smb_fname_dst)
5592{
5593	const char *psrc = smb_fname_src->base_name;
5594	const char *pdst = smb_fname_dst->base_name;
5595	size_t slen;
5596
5597	if (psrc[0] == '.' && psrc[1] == '/') {
5598		psrc += 2;
5599	}
5600	if (pdst[0] == '.' && pdst[1] == '/') {
5601		pdst += 2;
5602	}
5603	if ((slen = strlen(psrc)) > strlen(pdst)) {
5604		return False;
5605	}
5606	return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
5607}
5608
5609/*
5610 * Do the notify calls from a rename
5611 */
5612
5613static void notify_rename(connection_struct *conn, bool is_dir,
5614			  const struct smb_filename *smb_fname_src,
5615			  const struct smb_filename *smb_fname_dst)
5616{
5617	char *parent_dir_src = NULL;
5618	char *parent_dir_dst = NULL;
5619	uint32 mask;
5620
5621	mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
5622		: FILE_NOTIFY_CHANGE_FILE_NAME;
5623
5624	if (!parent_dirname(talloc_tos(), smb_fname_src->base_name,
5625			    &parent_dir_src, NULL) ||
5626	    !parent_dirname(talloc_tos(), smb_fname_dst->base_name,
5627			    &parent_dir_dst, NULL)) {
5628		goto out;
5629	}
5630
5631	if (strcmp(parent_dir_src, parent_dir_dst) == 0) {
5632		notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask,
5633			     smb_fname_src->base_name);
5634		notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask,
5635			     smb_fname_dst->base_name);
5636	}
5637	else {
5638		notify_fname(conn, NOTIFY_ACTION_REMOVED, mask,
5639			     smb_fname_src->base_name);
5640		notify_fname(conn, NOTIFY_ACTION_ADDED, mask,
5641			     smb_fname_dst->base_name);
5642	}
5643
5644	/* this is a strange one. w2k3 gives an additional event for
5645	   CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
5646	   files, but not directories */
5647	if (!is_dir) {
5648		notify_fname(conn, NOTIFY_ACTION_MODIFIED,
5649			     FILE_NOTIFY_CHANGE_ATTRIBUTES
5650			     |FILE_NOTIFY_CHANGE_CREATION,
5651			     smb_fname_dst->base_name);
5652	}
5653 out:
5654	TALLOC_FREE(parent_dir_src);
5655	TALLOC_FREE(parent_dir_dst);
5656}
5657
5658/****************************************************************************
5659 Rename an open file - given an fsp.
5660****************************************************************************/
5661
5662NTSTATUS rename_internals_fsp(connection_struct *conn,
5663			files_struct *fsp,
5664			const struct smb_filename *smb_fname_dst_in,
5665			uint32 attrs,
5666			bool replace_if_exists)
5667{
5668	TALLOC_CTX *ctx = talloc_tos();
5669	struct smb_filename *smb_fname_dst = NULL;
5670	NTSTATUS status = NT_STATUS_OK;
5671	struct share_mode_lock *lck = NULL;
5672	bool dst_exists, old_is_stream, new_is_stream;
5673
5674	status = check_name(conn, smb_fname_dst_in->base_name);
5675	if (!NT_STATUS_IS_OK(status)) {
5676		return status;
5677	}
5678
5679	/* Make a copy of the dst smb_fname structs */
5680
5681	status = copy_smb_filename(ctx, smb_fname_dst_in, &smb_fname_dst);
5682	if (!NT_STATUS_IS_OK(status)) {
5683		goto out;
5684	}
5685
5686	/* Ensure the dst smb_fname contains a '/' */
5687	if(strrchr_m(smb_fname_dst->base_name,'/') == 0) {
5688		char * tmp;
5689		tmp = talloc_asprintf(smb_fname_dst, "./%s",
5690				      smb_fname_dst->base_name);
5691		if (!tmp) {
5692			status = NT_STATUS_NO_MEMORY;
5693			goto out;
5694		}
5695		TALLOC_FREE(smb_fname_dst->base_name);
5696		smb_fname_dst->base_name = tmp;
5697	}
5698
5699	/*
5700	 * Check for special case with case preserving and not
5701	 * case sensitive. If the old last component differs from the original
5702	 * last component only by case, then we should allow
5703	 * the rename (user is trying to change the case of the
5704	 * filename).
5705	 */
5706	if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
5707	    strequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5708	    strequal(fsp->fsp_name->stream_name, smb_fname_dst->stream_name)) {
5709		char *last_slash;
5710		char *fname_dst_lcomp_base_mod = NULL;
5711		struct smb_filename *smb_fname_orig_lcomp = NULL;
5712
5713		/*
5714		 * Get the last component of the destination name.  Note that
5715		 * we guarantee that destination name contains a '/' character
5716		 * above.
5717		 */
5718		last_slash = strrchr_m(smb_fname_dst->base_name, '/');
5719		fname_dst_lcomp_base_mod = talloc_strdup(ctx, last_slash + 1);
5720		if (!fname_dst_lcomp_base_mod) {
5721			status = NT_STATUS_NO_MEMORY;
5722			goto out;
5723		}
5724
5725		/*
5726		 * Create an smb_filename struct using the original last
5727		 * component of the destination.
5728		 */
5729		status = create_synthetic_smb_fname_split(ctx,
5730		    smb_fname_dst->original_lcomp, NULL,
5731		    &smb_fname_orig_lcomp);
5732		if (!NT_STATUS_IS_OK(status)) {
5733			TALLOC_FREE(fname_dst_lcomp_base_mod);
5734			goto out;
5735		}
5736
5737		/* If the base names only differ by case, use original. */
5738		if(!strcsequal(fname_dst_lcomp_base_mod,
5739			       smb_fname_orig_lcomp->base_name)) {
5740			char *tmp;
5741			/*
5742			 * Replace the modified last component with the
5743			 * original.
5744			 */
5745			*last_slash = '\0'; /* Truncate at the '/' */
5746			tmp = talloc_asprintf(smb_fname_dst,
5747					"%s/%s",
5748					smb_fname_dst->base_name,
5749					smb_fname_orig_lcomp->base_name);
5750			if (tmp == NULL) {
5751				status = NT_STATUS_NO_MEMORY;
5752				TALLOC_FREE(fname_dst_lcomp_base_mod);
5753				TALLOC_FREE(smb_fname_orig_lcomp);
5754				goto out;
5755			}
5756			TALLOC_FREE(smb_fname_dst->base_name);
5757			smb_fname_dst->base_name = tmp;
5758		}
5759
5760		/* If the stream_names only differ by case, use original. */
5761		if(!strcsequal(smb_fname_dst->stream_name,
5762			       smb_fname_orig_lcomp->stream_name)) {
5763			char *tmp = NULL;
5764			/* Use the original stream. */
5765			tmp = talloc_strdup(smb_fname_dst,
5766					    smb_fname_orig_lcomp->stream_name);
5767			if (tmp == NULL) {
5768				status = NT_STATUS_NO_MEMORY;
5769				TALLOC_FREE(fname_dst_lcomp_base_mod);
5770				TALLOC_FREE(smb_fname_orig_lcomp);
5771				goto out;
5772			}
5773			TALLOC_FREE(smb_fname_dst->stream_name);
5774			smb_fname_dst->stream_name = tmp;
5775		}
5776		TALLOC_FREE(fname_dst_lcomp_base_mod);
5777		TALLOC_FREE(smb_fname_orig_lcomp);
5778	}
5779
5780	/*
5781	 * If the src and dest names are identical - including case,
5782	 * don't do the rename, just return success.
5783	 */
5784
5785	if (strcsequal(fsp->fsp_name->base_name, smb_fname_dst->base_name) &&
5786	    strcsequal(fsp->fsp_name->stream_name,
5787		       smb_fname_dst->stream_name)) {
5788		DEBUG(3, ("rename_internals_fsp: identical names in rename %s "
5789			  "- returning success\n",
5790			  smb_fname_str_dbg(smb_fname_dst)));
5791		status = NT_STATUS_OK;
5792		goto out;
5793	}
5794
5795	old_is_stream = is_ntfs_stream_smb_fname(fsp->fsp_name);
5796	new_is_stream = is_ntfs_stream_smb_fname(smb_fname_dst);
5797
5798	/* Return the correct error code if both names aren't streams. */
5799	if (!old_is_stream && new_is_stream) {
5800		status = NT_STATUS_OBJECT_NAME_INVALID;
5801		goto out;
5802	}
5803
5804	if (old_is_stream && !new_is_stream) {
5805		status = NT_STATUS_INVALID_PARAMETER;
5806		goto out;
5807	}
5808
5809	dst_exists = SMB_VFS_STAT(conn, smb_fname_dst) == 0;
5810
5811	if(!replace_if_exists && dst_exists) {
5812		DEBUG(3, ("rename_internals_fsp: dest exists doing rename "
5813			  "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
5814			  smb_fname_str_dbg(smb_fname_dst)));
5815		status = NT_STATUS_OBJECT_NAME_COLLISION;
5816		goto out;
5817	}
5818
5819	if (dst_exists) {
5820		struct file_id fileid = vfs_file_id_from_sbuf(conn,
5821		    &smb_fname_dst->st);
5822		files_struct *dst_fsp = file_find_di_first(fileid);
5823		/* The file can be open when renaming a stream */
5824		if (dst_fsp && !new_is_stream) {
5825			DEBUG(3, ("rename_internals_fsp: Target file open\n"));
5826			status = NT_STATUS_ACCESS_DENIED;
5827			goto out;
5828		}
5829	}
5830
5831	/* Ensure we have a valid stat struct for the source. */
5832	status = vfs_stat_fsp(fsp);
5833	if (!NT_STATUS_IS_OK(status)) {
5834		goto out;
5835	}
5836
5837	status = can_rename(conn, fsp, attrs);
5838
5839	if (!NT_STATUS_IS_OK(status)) {
5840		DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
5841			  nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
5842			  smb_fname_str_dbg(smb_fname_dst)));
5843		if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
5844			status = NT_STATUS_ACCESS_DENIED;
5845		goto out;
5846	}
5847
5848	if (rename_path_prefix_equal(fsp->fsp_name, smb_fname_dst)) {
5849		status = NT_STATUS_ACCESS_DENIED;
5850	}
5851
5852	lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
5853				  NULL);
5854
5855	/*
5856	 * We have the file open ourselves, so not being able to get the
5857	 * corresponding share mode lock is a fatal error.
5858	 */
5859
5860	SMB_ASSERT(lck != NULL);
5861
5862	if(SMB_VFS_RENAME(conn, fsp->fsp_name, smb_fname_dst) == 0) {
5863		uint32 create_options = fsp->fh->private_options;
5864
5865		DEBUG(3, ("rename_internals_fsp: succeeded doing rename on "
5866			  "%s -> %s\n", smb_fname_str_dbg(fsp->fsp_name),
5867			  smb_fname_str_dbg(smb_fname_dst)));
5868
5869		if (!lp_posix_pathnames() &&
5870		    (lp_map_archive(SNUM(conn)) ||
5871		    lp_store_dos_attributes(SNUM(conn)))) {
5872			/* We must set the archive bit on the newly
5873			   renamed file. */
5874			if (SMB_VFS_STAT(conn, smb_fname_dst) == 0) {
5875				uint32_t old_dosmode = dos_mode(conn,
5876							smb_fname_dst);
5877				file_set_dosmode(conn,
5878					smb_fname_dst,
5879					old_dosmode | FILE_ATTRIBUTE_ARCHIVE,
5880					NULL,
5881					true);
5882			}
5883		}
5884
5885		notify_rename(conn, fsp->is_directory, fsp->fsp_name,
5886			      smb_fname_dst);
5887
5888		rename_open_files(conn, lck, smb_fname_dst);
5889
5890		/*
5891		 * A rename acts as a new file create w.r.t. allowing an initial delete
5892		 * on close, probably because in Windows there is a new handle to the
5893		 * new file. If initial delete on close was requested but not
5894		 * originally set, we need to set it here. This is probably not 100% correct,
5895		 * but will work for the CIFSFS client which in non-posix mode
5896		 * depends on these semantics. JRA.
5897		 */
5898
5899		if (create_options & FILE_DELETE_ON_CLOSE) {
5900			status = can_set_delete_on_close(fsp, 0);
5901
5902			if (NT_STATUS_IS_OK(status)) {
5903				/* Note that here we set the *inital* delete on close flag,
5904				 * not the regular one. The magic gets handled in close. */
5905				fsp->initial_delete_on_close = True;
5906			}
5907		}
5908		TALLOC_FREE(lck);
5909		status = NT_STATUS_OK;
5910		goto out;
5911	}
5912
5913	TALLOC_FREE(lck);
5914
5915	if (errno == ENOTDIR || errno == EISDIR) {
5916		status = NT_STATUS_OBJECT_NAME_COLLISION;
5917	} else {
5918		status = map_nt_error_from_unix(errno);
5919	}
5920
5921	DEBUG(3, ("rename_internals_fsp: Error %s rename %s -> %s\n",
5922		  nt_errstr(status), smb_fname_str_dbg(fsp->fsp_name),
5923		  smb_fname_str_dbg(smb_fname_dst)));
5924
5925 out:
5926	TALLOC_FREE(smb_fname_dst);
5927
5928	return status;
5929}
5930
5931/****************************************************************************
5932 The guts of the rename command, split out so it may be called by the NT SMB
5933 code.
5934****************************************************************************/
5935
5936NTSTATUS rename_internals(TALLOC_CTX *ctx,
5937			connection_struct *conn,
5938			struct smb_request *req,
5939			struct smb_filename *smb_fname_src,
5940			struct smb_filename *smb_fname_dst,
5941			uint32 attrs,
5942			bool replace_if_exists,
5943			bool src_has_wild,
5944			bool dest_has_wild,
5945			uint32_t access_mask)
5946{
5947	char *fname_src_dir = NULL;
5948	char *fname_src_mask = NULL;
5949	int count=0;
5950	NTSTATUS status = NT_STATUS_OK;
5951	struct smb_Dir *dir_hnd = NULL;
5952	const char *dname = NULL;
5953	char *talloced = NULL;
5954	long offset = 0;
5955	int create_options = 0;
5956	bool posix_pathnames = lp_posix_pathnames();
5957
5958	/*
5959	 * Split the old name into directory and last component
5960	 * strings. Note that unix_convert may have stripped off a
5961	 * leading ./ from both name and newname if the rename is
5962	 * at the root of the share. We need to make sure either both
5963	 * name and newname contain a / character or neither of them do
5964	 * as this is checked in resolve_wildcards().
5965	 */
5966
5967	/* Split up the directory from the filename/mask. */
5968	status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
5969				      &fname_src_dir, &fname_src_mask);
5970	if (!NT_STATUS_IS_OK(status)) {
5971		status = NT_STATUS_NO_MEMORY;
5972		goto out;
5973	}
5974
5975	/*
5976	 * We should only check the mangled cache
5977	 * here if unix_convert failed. This means
5978	 * that the path in 'mask' doesn't exist
5979	 * on the file system and so we need to look
5980	 * for a possible mangle. This patch from
5981	 * Tine Smukavec <valentin.smukavec@hermes.si>.
5982	 */
5983
5984	if (!VALID_STAT(smb_fname_src->st) &&
5985	    mangle_is_mangled(fname_src_mask, conn->params)) {
5986		char *new_mask = NULL;
5987		mangle_lookup_name_from_8_3(ctx, fname_src_mask, &new_mask,
5988					    conn->params);
5989		if (new_mask) {
5990			TALLOC_FREE(fname_src_mask);
5991			fname_src_mask = new_mask;
5992		}
5993	}
5994
5995	if (!src_has_wild) {
5996		files_struct *fsp;
5997
5998		/*
5999		 * Only one file needs to be renamed. Append the mask back
6000		 * onto the directory.
6001		 */
6002		TALLOC_FREE(smb_fname_src->base_name);
6003		smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6004							   "%s/%s",
6005							   fname_src_dir,
6006							   fname_src_mask);
6007		if (!smb_fname_src->base_name) {
6008			status = NT_STATUS_NO_MEMORY;
6009			goto out;
6010		}
6011
6012		/* Ensure dst fname contains a '/' also */
6013		if(strrchr_m(smb_fname_dst->base_name, '/') == 0) {
6014			char *tmp;
6015			tmp = talloc_asprintf(smb_fname_dst, "./%s",
6016					      smb_fname_dst->base_name);
6017			if (!tmp) {
6018				status = NT_STATUS_NO_MEMORY;
6019				goto out;
6020			}
6021			TALLOC_FREE(smb_fname_dst->base_name);
6022			smb_fname_dst->base_name = tmp;
6023		}
6024
6025		DEBUG(3, ("rename_internals: case_sensitive = %d, "
6026			  "case_preserve = %d, short case preserve = %d, "
6027			  "directory = %s, newname = %s, "
6028			  "last_component_dest = %s\n",
6029			  conn->case_sensitive, conn->case_preserve,
6030			  conn->short_case_preserve,
6031			  smb_fname_str_dbg(smb_fname_src),
6032			  smb_fname_str_dbg(smb_fname_dst),
6033			  smb_fname_dst->original_lcomp));
6034
6035		/* The dest name still may have wildcards. */
6036		if (dest_has_wild) {
6037			char *fname_dst_mod = NULL;
6038			if (!resolve_wildcards(smb_fname_dst,
6039					       smb_fname_src->base_name,
6040					       smb_fname_dst->base_name,
6041					       &fname_dst_mod)) {
6042				DEBUG(6, ("rename_internals: resolve_wildcards "
6043					  "%s %s failed\n",
6044					  smb_fname_src->base_name,
6045					  smb_fname_dst->base_name));
6046				status = NT_STATUS_NO_MEMORY;
6047				goto out;
6048			}
6049			TALLOC_FREE(smb_fname_dst->base_name);
6050			smb_fname_dst->base_name = fname_dst_mod;
6051		}
6052
6053		ZERO_STRUCT(smb_fname_src->st);
6054		if (posix_pathnames) {
6055			SMB_VFS_LSTAT(conn, smb_fname_src);
6056		} else {
6057			SMB_VFS_STAT(conn, smb_fname_src);
6058		}
6059
6060		if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6061			create_options |= FILE_DIRECTORY_FILE;
6062		}
6063
6064		status = SMB_VFS_CREATE_FILE(
6065			conn,				/* conn */
6066			req,				/* req */
6067			0,				/* root_dir_fid */
6068			smb_fname_src,			/* fname */
6069			access_mask,			/* access_mask */
6070			(FILE_SHARE_READ |		/* share_access */
6071			    FILE_SHARE_WRITE),
6072			FILE_OPEN,			/* create_disposition*/
6073			create_options,			/* create_options */
6074			posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6075			0,				/* oplock_request */
6076			0,				/* allocation_size */
6077			NULL,				/* sd */
6078			NULL,				/* ea_list */
6079			&fsp,				/* result */
6080			NULL);				/* pinfo */
6081
6082		if (!NT_STATUS_IS_OK(status)) {
6083			DEBUG(3, ("Could not open rename source %s: %s\n",
6084				  smb_fname_str_dbg(smb_fname_src),
6085				  nt_errstr(status)));
6086			goto out;
6087		}
6088
6089		status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6090					      attrs, replace_if_exists);
6091
6092		close_file(req, fsp, NORMAL_CLOSE);
6093
6094		DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
6095			  nt_errstr(status), smb_fname_str_dbg(smb_fname_src),
6096			  smb_fname_str_dbg(smb_fname_dst)));
6097
6098		goto out;
6099	}
6100
6101	/*
6102	 * Wildcards - process each file that matches.
6103	 */
6104	if (strequal(fname_src_mask, "????????.???")) {
6105		TALLOC_FREE(fname_src_mask);
6106		fname_src_mask = talloc_strdup(ctx, "*");
6107		if (!fname_src_mask) {
6108			status = NT_STATUS_NO_MEMORY;
6109			goto out;
6110		}
6111	}
6112
6113	status = check_name(conn, fname_src_dir);
6114	if (!NT_STATUS_IS_OK(status)) {
6115		goto out;
6116	}
6117
6118	dir_hnd = OpenDir(talloc_tos(), conn, fname_src_dir, fname_src_mask,
6119			  attrs);
6120	if (dir_hnd == NULL) {
6121		status = map_nt_error_from_unix(errno);
6122		goto out;
6123	}
6124
6125	status = NT_STATUS_NO_SUCH_FILE;
6126	/*
6127	 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6128	 * - gentest fix. JRA
6129	 */
6130
6131	while ((dname = ReadDirName(dir_hnd, &offset, &smb_fname_src->st,
6132				    &talloced))) {
6133		files_struct *fsp = NULL;
6134		char *destname = NULL;
6135		bool sysdir_entry = False;
6136
6137		/* Quick check for "." and ".." */
6138		if (ISDOT(dname) || ISDOTDOT(dname)) {
6139			if (attrs & aDIR) {
6140				sysdir_entry = True;
6141			} else {
6142				TALLOC_FREE(talloced);
6143				continue;
6144			}
6145		}
6146
6147		if (!is_visible_file(conn, fname_src_dir, dname,
6148				     &smb_fname_src->st, false)) {
6149			TALLOC_FREE(talloced);
6150			continue;
6151		}
6152
6153		if(!mask_match(dname, fname_src_mask, conn->case_sensitive)) {
6154			TALLOC_FREE(talloced);
6155			continue;
6156		}
6157
6158		if (sysdir_entry) {
6159			status = NT_STATUS_OBJECT_NAME_INVALID;
6160			break;
6161		}
6162
6163		TALLOC_FREE(smb_fname_src->base_name);
6164		smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6165							   "%s/%s",
6166							   fname_src_dir,
6167							   dname);
6168		if (!smb_fname_src->base_name) {
6169			status = NT_STATUS_NO_MEMORY;
6170			goto out;
6171		}
6172
6173		if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6174				       smb_fname_dst->base_name,
6175				       &destname)) {
6176			DEBUG(6, ("resolve_wildcards %s %s failed\n",
6177				  smb_fname_src->base_name, destname));
6178			TALLOC_FREE(talloced);
6179			continue;
6180		}
6181		if (!destname) {
6182			status = NT_STATUS_NO_MEMORY;
6183			goto out;
6184		}
6185
6186		TALLOC_FREE(smb_fname_dst->base_name);
6187		smb_fname_dst->base_name = destname;
6188
6189		ZERO_STRUCT(smb_fname_src->st);
6190		if (posix_pathnames) {
6191			SMB_VFS_LSTAT(conn, smb_fname_src);
6192		} else {
6193			SMB_VFS_STAT(conn, smb_fname_src);
6194		}
6195
6196		create_options = 0;
6197
6198		if (S_ISDIR(smb_fname_src->st.st_ex_mode)) {
6199			create_options |= FILE_DIRECTORY_FILE;
6200		}
6201
6202		status = SMB_VFS_CREATE_FILE(
6203			conn,				/* conn */
6204			req,				/* req */
6205			0,				/* root_dir_fid */
6206			smb_fname_src,			/* fname */
6207			access_mask,			/* access_mask */
6208			(FILE_SHARE_READ |		/* share_access */
6209			    FILE_SHARE_WRITE),
6210			FILE_OPEN,			/* create_disposition*/
6211			create_options,			/* create_options */
6212			posix_pathnames ? FILE_FLAG_POSIX_SEMANTICS|0777 : 0, /* file_attributes */
6213			0,				/* oplock_request */
6214			0,				/* allocation_size */
6215			NULL,				/* sd */
6216			NULL,				/* ea_list */
6217			&fsp,				/* result */
6218			NULL);				/* pinfo */
6219
6220		if (!NT_STATUS_IS_OK(status)) {
6221			DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
6222				 "returned %s rename %s -> %s\n",
6223				 nt_errstr(status),
6224				 smb_fname_str_dbg(smb_fname_src),
6225				 smb_fname_str_dbg(smb_fname_dst)));
6226			break;
6227		}
6228
6229		smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6230							      dname);
6231		if (!smb_fname_dst->original_lcomp) {
6232			status = NT_STATUS_NO_MEMORY;
6233			goto out;
6234		}
6235
6236		status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6237					      attrs, replace_if_exists);
6238
6239		close_file(req, fsp, NORMAL_CLOSE);
6240
6241		if (!NT_STATUS_IS_OK(status)) {
6242			DEBUG(3, ("rename_internals_fsp returned %s for "
6243				  "rename %s -> %s\n", nt_errstr(status),
6244				  smb_fname_str_dbg(smb_fname_src),
6245				  smb_fname_str_dbg(smb_fname_dst)));
6246			break;
6247		}
6248
6249		count++;
6250
6251		DEBUG(3,("rename_internals: doing rename on %s -> "
6252			 "%s\n", smb_fname_str_dbg(smb_fname_src),
6253			 smb_fname_str_dbg(smb_fname_src)));
6254		TALLOC_FREE(talloced);
6255	}
6256	TALLOC_FREE(dir_hnd);
6257
6258	if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
6259		status = map_nt_error_from_unix(errno);
6260	}
6261
6262 out:
6263	TALLOC_FREE(talloced);
6264	TALLOC_FREE(fname_src_dir);
6265	TALLOC_FREE(fname_src_mask);
6266	return status;
6267}
6268
6269/****************************************************************************
6270 Reply to a mv.
6271****************************************************************************/
6272
6273void reply_mv(struct smb_request *req)
6274{
6275	connection_struct *conn = req->conn;
6276	char *name = NULL;
6277	char *newname = NULL;
6278	const char *p;
6279	uint32 attrs;
6280	NTSTATUS status;
6281	bool src_has_wcard = False;
6282	bool dest_has_wcard = False;
6283	TALLOC_CTX *ctx = talloc_tos();
6284	struct smb_filename *smb_fname_src = NULL;
6285	struct smb_filename *smb_fname_dst = NULL;
6286
6287	START_PROFILE(SMBmv);
6288
6289	if (req->wct < 1) {
6290		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6291		goto out;
6292	}
6293
6294	attrs = SVAL(req->vwv+0, 0);
6295
6296	p = (const char *)req->buf + 1;
6297	p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
6298				       &status, &src_has_wcard);
6299	if (!NT_STATUS_IS_OK(status)) {
6300		reply_nterror(req, status);
6301		goto out;
6302	}
6303	p++;
6304	p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
6305				       &status, &dest_has_wcard);
6306	if (!NT_STATUS_IS_OK(status)) {
6307		reply_nterror(req, status);
6308		goto out;
6309	}
6310
6311	status = filename_convert(ctx,
6312				  conn,
6313				  req->flags2 & FLAGS2_DFS_PATHNAMES,
6314				  name,
6315				  UCF_COND_ALLOW_WCARD_LCOMP,
6316				  &src_has_wcard,
6317				  &smb_fname_src);
6318
6319	if (!NT_STATUS_IS_OK(status)) {
6320		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6321			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6322					ERRSRV, ERRbadpath);
6323			goto out;
6324		}
6325		reply_nterror(req, status);
6326		goto out;
6327	}
6328
6329	status = filename_convert(ctx,
6330				  conn,
6331				  req->flags2 & FLAGS2_DFS_PATHNAMES,
6332				  newname,
6333				  UCF_COND_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP,
6334				  &dest_has_wcard,
6335				  &smb_fname_dst);
6336
6337	if (!NT_STATUS_IS_OK(status)) {
6338		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6339			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6340					ERRSRV, ERRbadpath);
6341			goto out;
6342		}
6343		reply_nterror(req, status);
6344		goto out;
6345	}
6346
6347	DEBUG(3,("reply_mv : %s -> %s\n", smb_fname_str_dbg(smb_fname_src),
6348		 smb_fname_str_dbg(smb_fname_dst)));
6349
6350	status = rename_internals(ctx, conn, req, smb_fname_src, smb_fname_dst,
6351				  attrs, False, src_has_wcard, dest_has_wcard,
6352				  DELETE_ACCESS);
6353	if (!NT_STATUS_IS_OK(status)) {
6354		if (open_was_deferred(req->mid)) {
6355			/* We have re-scheduled this call. */
6356			goto out;
6357		}
6358		reply_nterror(req, status);
6359		goto out;
6360	}
6361
6362	reply_outbuf(req, 0, 0);
6363 out:
6364	TALLOC_FREE(smb_fname_src);
6365	TALLOC_FREE(smb_fname_dst);
6366	END_PROFILE(SMBmv);
6367	return;
6368}
6369
6370/*******************************************************************
6371 Copy a file as part of a reply_copy.
6372******************************************************************/
6373
6374/*
6375 * TODO: check error codes on all callers
6376 */
6377
6378NTSTATUS copy_file(TALLOC_CTX *ctx,
6379			connection_struct *conn,
6380			struct smb_filename *smb_fname_src,
6381			struct smb_filename *smb_fname_dst,
6382			int ofun,
6383			int count,
6384			bool target_is_directory)
6385{
6386	struct smb_filename *smb_fname_dst_tmp = NULL;
6387	SMB_OFF_T ret=-1;
6388	files_struct *fsp1,*fsp2;
6389 	uint32 dosattrs;
6390	uint32 new_create_disposition;
6391	NTSTATUS status;
6392
6393
6394	status = copy_smb_filename(ctx, smb_fname_dst, &smb_fname_dst_tmp);
6395	if (!NT_STATUS_IS_OK(status)) {
6396		return status;
6397	}
6398
6399	/*
6400	 * If the target is a directory, extract the last component from the
6401	 * src filename and append it to the dst filename
6402	 */
6403	if (target_is_directory) {
6404		const char *p;
6405
6406		/* dest/target can't be a stream if it's a directory. */
6407		SMB_ASSERT(smb_fname_dst->stream_name == NULL);
6408
6409		p = strrchr_m(smb_fname_src->base_name,'/');
6410		if (p) {
6411			p++;
6412		} else {
6413			p = smb_fname_src->base_name;
6414		}
6415		smb_fname_dst_tmp->base_name =
6416		    talloc_asprintf_append(smb_fname_dst_tmp->base_name, "/%s",
6417					   p);
6418		if (!smb_fname_dst_tmp->base_name) {
6419			status = NT_STATUS_NO_MEMORY;
6420			goto out;
6421		}
6422	}
6423
6424	status = vfs_file_exist(conn, smb_fname_src);
6425	if (!NT_STATUS_IS_OK(status)) {
6426		goto out;
6427	}
6428
6429	if (!target_is_directory && count) {
6430		new_create_disposition = FILE_OPEN;
6431	} else {
6432		if (!map_open_params_to_ntcreate(smb_fname_dst_tmp->base_name,
6433						 0, ofun,
6434						 NULL, NULL,
6435						 &new_create_disposition,
6436						 NULL)) {
6437			status = NT_STATUS_INVALID_PARAMETER;
6438			goto out;
6439		}
6440	}
6441
6442	/* Open the src file for reading. */
6443	status = SMB_VFS_CREATE_FILE(
6444		conn,					/* conn */
6445		NULL,					/* req */
6446		0,					/* root_dir_fid */
6447		smb_fname_src,	       			/* fname */
6448		FILE_GENERIC_READ,			/* access_mask */
6449		FILE_SHARE_READ | FILE_SHARE_WRITE,	/* share_access */
6450		FILE_OPEN,				/* create_disposition*/
6451		0,					/* create_options */
6452		FILE_ATTRIBUTE_NORMAL,			/* file_attributes */
6453		INTERNAL_OPEN_ONLY,			/* oplock_request */
6454		0,					/* allocation_size */
6455		NULL,					/* sd */
6456		NULL,					/* ea_list */
6457		&fsp1,					/* result */
6458		NULL);					/* psbuf */
6459
6460	if (!NT_STATUS_IS_OK(status)) {
6461		goto out;
6462	}
6463
6464	dosattrs = dos_mode(conn, smb_fname_src);
6465
6466	if (SMB_VFS_STAT(conn, smb_fname_dst_tmp) == -1) {
6467		ZERO_STRUCTP(&smb_fname_dst_tmp->st);
6468	}
6469
6470	/* Open the dst file for writing. */
6471	status = SMB_VFS_CREATE_FILE(
6472		conn,					/* conn */
6473		NULL,					/* req */
6474		0,					/* root_dir_fid */
6475		smb_fname_dst,				/* fname */
6476		FILE_GENERIC_WRITE,			/* access_mask */
6477		FILE_SHARE_READ | FILE_SHARE_WRITE,	/* share_access */
6478		new_create_disposition,			/* create_disposition*/
6479		0,					/* create_options */
6480		dosattrs,				/* file_attributes */
6481		INTERNAL_OPEN_ONLY,			/* oplock_request */
6482		0,					/* allocation_size */
6483		NULL,					/* sd */
6484		NULL,					/* ea_list */
6485		&fsp2,					/* result */
6486		NULL);					/* psbuf */
6487
6488	if (!NT_STATUS_IS_OK(status)) {
6489		close_file(NULL, fsp1, ERROR_CLOSE);
6490		goto out;
6491	}
6492
6493	if ((ofun&3) == 1) {
6494		if(SMB_VFS_LSEEK(fsp2,0,SEEK_END) == -1) {
6495			DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
6496			/*
6497			 * Stop the copy from occurring.
6498			 */
6499			ret = -1;
6500			smb_fname_src->st.st_ex_size = 0;
6501		}
6502	}
6503
6504	/* Do the actual copy. */
6505	if (smb_fname_src->st.st_ex_size) {
6506		ret = vfs_transfer_file(fsp1, fsp2, smb_fname_src->st.st_ex_size);
6507	}
6508
6509	close_file(NULL, fsp1, NORMAL_CLOSE);
6510
6511	/* Ensure the modtime is set correctly on the destination file. */
6512	set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime);
6513
6514	/*
6515	 * As we are opening fsp1 read-only we only expect
6516	 * an error on close on fsp2 if we are out of space.
6517	 * Thus we don't look at the error return from the
6518	 * close of fsp1.
6519	 */
6520	status = close_file(NULL, fsp2, NORMAL_CLOSE);
6521
6522	if (!NT_STATUS_IS_OK(status)) {
6523		goto out;
6524	}
6525
6526	if (ret != (SMB_OFF_T)smb_fname_src->st.st_ex_size) {
6527		status = NT_STATUS_DISK_FULL;
6528		goto out;
6529	}
6530
6531	status = NT_STATUS_OK;
6532
6533 out:
6534	TALLOC_FREE(smb_fname_dst_tmp);
6535	return status;
6536}
6537
6538/****************************************************************************
6539 Reply to a file copy.
6540****************************************************************************/
6541
6542void reply_copy(struct smb_request *req)
6543{
6544	connection_struct *conn = req->conn;
6545	struct smb_filename *smb_fname_src = NULL;
6546	struct smb_filename *smb_fname_dst = NULL;
6547	char *fname_src = NULL;
6548	char *fname_dst = NULL;
6549	char *fname_src_mask = NULL;
6550	char *fname_src_dir = NULL;
6551	const char *p;
6552	int count=0;
6553	int error = ERRnoaccess;
6554	int tid2;
6555	int ofun;
6556	int flags;
6557	bool target_is_directory=False;
6558	bool source_has_wild = False;
6559	bool dest_has_wild = False;
6560	NTSTATUS status;
6561	TALLOC_CTX *ctx = talloc_tos();
6562
6563	START_PROFILE(SMBcopy);
6564
6565	if (req->wct < 3) {
6566		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6567		goto out;
6568	}
6569
6570	tid2 = SVAL(req->vwv+0, 0);
6571	ofun = SVAL(req->vwv+1, 0);
6572	flags = SVAL(req->vwv+2, 0);
6573
6574	p = (const char *)req->buf;
6575	p += srvstr_get_path_req_wcard(ctx, req, &fname_src, p, STR_TERMINATE,
6576				       &status, &source_has_wild);
6577	if (!NT_STATUS_IS_OK(status)) {
6578		reply_nterror(req, status);
6579		goto out;
6580	}
6581	p += srvstr_get_path_req_wcard(ctx, req, &fname_dst, p, STR_TERMINATE,
6582				       &status, &dest_has_wild);
6583	if (!NT_STATUS_IS_OK(status)) {
6584		reply_nterror(req, status);
6585		goto out;
6586	}
6587
6588	DEBUG(3,("reply_copy : %s -> %s\n", fname_src, fname_dst));
6589
6590	if (tid2 != conn->cnum) {
6591		/* can't currently handle inter share copies XXXX */
6592		DEBUG(3,("Rejecting inter-share copy\n"));
6593		reply_nterror(req, NT_STATUS_BAD_DEVICE_TYPE);
6594		goto out;
6595	}
6596
6597	status = filename_convert(ctx, conn,
6598				  req->flags2 & FLAGS2_DFS_PATHNAMES,
6599				  fname_src,
6600				  UCF_COND_ALLOW_WCARD_LCOMP,
6601				  &source_has_wild,
6602				  &smb_fname_src);
6603	if (!NT_STATUS_IS_OK(status)) {
6604		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6605			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6606					ERRSRV, ERRbadpath);
6607			goto out;
6608		}
6609		reply_nterror(req, status);
6610		goto out;
6611	}
6612
6613	status = filename_convert(ctx, conn,
6614				  req->flags2 & FLAGS2_DFS_PATHNAMES,
6615				  fname_dst,
6616				  UCF_COND_ALLOW_WCARD_LCOMP,
6617				  &dest_has_wild,
6618				  &smb_fname_dst);
6619	if (!NT_STATUS_IS_OK(status)) {
6620		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6621			reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6622					ERRSRV, ERRbadpath);
6623			goto out;
6624		}
6625		reply_nterror(req, status);
6626		goto out;
6627	}
6628
6629	target_is_directory = VALID_STAT_OF_DIR(smb_fname_dst->st);
6630
6631	if ((flags&1) && target_is_directory) {
6632		reply_nterror(req, NT_STATUS_NO_SUCH_FILE);
6633		goto out;
6634	}
6635
6636	if ((flags&2) && !target_is_directory) {
6637		reply_nterror(req, NT_STATUS_OBJECT_PATH_NOT_FOUND);
6638		goto out;
6639	}
6640
6641	if ((flags&(1<<5)) && VALID_STAT_OF_DIR(smb_fname_src->st)) {
6642		/* wants a tree copy! XXXX */
6643		DEBUG(3,("Rejecting tree copy\n"));
6644		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6645		goto out;
6646	}
6647
6648	/* Split up the directory from the filename/mask. */
6649	status = split_fname_dir_mask(ctx, smb_fname_src->base_name,
6650				      &fname_src_dir, &fname_src_mask);
6651	if (!NT_STATUS_IS_OK(status)) {
6652		reply_nterror(req, NT_STATUS_NO_MEMORY);
6653		goto out;
6654	}
6655
6656	/*
6657	 * We should only check the mangled cache
6658	 * here if unix_convert failed. This means
6659	 * that the path in 'mask' doesn't exist
6660	 * on the file system and so we need to look
6661	 * for a possible mangle. This patch from
6662	 * Tine Smukavec <valentin.smukavec@hermes.si>.
6663	 */
6664	if (!VALID_STAT(smb_fname_src->st) &&
6665	    mangle_is_mangled(fname_src_mask, conn->params)) {
6666		char *new_mask = NULL;
6667		mangle_lookup_name_from_8_3(ctx, fname_src_mask,
6668					    &new_mask, conn->params);
6669
6670		/* Use demangled name if one was successfully found. */
6671		if (new_mask) {
6672			TALLOC_FREE(fname_src_mask);
6673			fname_src_mask = new_mask;
6674		}
6675	}
6676
6677	if (!source_has_wild) {
6678
6679		/*
6680		 * Only one file needs to be copied. Append the mask back onto
6681		 * the directory.
6682		 */
6683		TALLOC_FREE(smb_fname_src->base_name);
6684		smb_fname_src->base_name = talloc_asprintf(smb_fname_src,
6685							   "%s/%s",
6686							   fname_src_dir,
6687							   fname_src_mask);
6688		if (!smb_fname_src->base_name) {
6689			reply_nterror(req, NT_STATUS_NO_MEMORY);
6690			goto out;
6691		}
6692
6693		if (dest_has_wild) {
6694			char *fname_dst_mod = NULL;
6695			if (!resolve_wildcards(smb_fname_dst,
6696					       smb_fname_src->base_name,
6697					       smb_fname_dst->base_name,
6698					       &fname_dst_mod)) {
6699				reply_nterror(req, NT_STATUS_NO_MEMORY);
6700				goto out;
6701			}
6702			TALLOC_FREE(smb_fname_dst->base_name);
6703			smb_fname_dst->base_name = fname_dst_mod;
6704		}
6705
6706		status = check_name(conn, smb_fname_src->base_name);
6707		if (!NT_STATUS_IS_OK(status)) {
6708			reply_nterror(req, status);
6709			goto out;
6710		}
6711
6712		status = check_name(conn, smb_fname_dst->base_name);
6713		if (!NT_STATUS_IS_OK(status)) {
6714			reply_nterror(req, status);
6715			goto out;
6716		}
6717
6718		status = copy_file(ctx, conn, smb_fname_src, smb_fname_dst,
6719				   ofun, count, target_is_directory);
6720
6721		if(!NT_STATUS_IS_OK(status)) {
6722			reply_nterror(req, status);
6723			goto out;
6724		} else {
6725			count++;
6726		}
6727	} else {
6728		struct smb_Dir *dir_hnd = NULL;
6729		const char *dname = NULL;
6730		char *talloced = NULL;
6731		long offset = 0;
6732
6733		/*
6734		 * There is a wildcard that requires us to actually read the
6735		 * src dir and copy each file matching the mask to the dst.
6736		 * Right now streams won't be copied, but this could
6737		 * presumably be added with a nested loop for reach dir entry.
6738		 */
6739		SMB_ASSERT(!smb_fname_src->stream_name);
6740		SMB_ASSERT(!smb_fname_dst->stream_name);
6741
6742		smb_fname_src->stream_name = NULL;
6743		smb_fname_dst->stream_name = NULL;
6744
6745		if (strequal(fname_src_mask,"????????.???")) {
6746			TALLOC_FREE(fname_src_mask);
6747			fname_src_mask = talloc_strdup(ctx, "*");
6748			if (!fname_src_mask) {
6749				reply_nterror(req, NT_STATUS_NO_MEMORY);
6750				goto out;
6751			}
6752		}
6753
6754		status = check_name(conn, fname_src_dir);
6755		if (!NT_STATUS_IS_OK(status)) {
6756			reply_nterror(req, status);
6757			goto out;
6758		}
6759
6760		dir_hnd = OpenDir(ctx, conn, fname_src_dir, fname_src_mask, 0);
6761		if (dir_hnd == NULL) {
6762			status = map_nt_error_from_unix(errno);
6763			reply_nterror(req, status);
6764			goto out;
6765		}
6766
6767		error = ERRbadfile;
6768
6769		/* Iterate over the src dir copying each entry to the dst. */
6770		while ((dname = ReadDirName(dir_hnd, &offset,
6771					    &smb_fname_src->st, &talloced))) {
6772			char *destname = NULL;
6773
6774			if (ISDOT(dname) || ISDOTDOT(dname)) {
6775				TALLOC_FREE(talloced);
6776				continue;
6777			}
6778
6779			if (!is_visible_file(conn, fname_src_dir, dname,
6780					     &smb_fname_src->st, false)) {
6781				TALLOC_FREE(talloced);
6782				continue;
6783			}
6784
6785			if(!mask_match(dname, fname_src_mask,
6786				       conn->case_sensitive)) {
6787				TALLOC_FREE(talloced);
6788				continue;
6789			}
6790
6791			error = ERRnoaccess;
6792
6793			/* Get the src smb_fname struct setup. */
6794			TALLOC_FREE(smb_fname_src->base_name);
6795			smb_fname_src->base_name =
6796			    talloc_asprintf(smb_fname_src, "%s/%s",
6797					    fname_src_dir, dname);
6798
6799			if (!smb_fname_src->base_name) {
6800				TALLOC_FREE(dir_hnd);
6801				TALLOC_FREE(talloced);
6802				reply_nterror(req, NT_STATUS_NO_MEMORY);
6803				goto out;
6804			}
6805
6806			if (!resolve_wildcards(ctx, smb_fname_src->base_name,
6807					       smb_fname_dst->base_name,
6808					       &destname)) {
6809				TALLOC_FREE(talloced);
6810				continue;
6811			}
6812			if (!destname) {
6813				TALLOC_FREE(dir_hnd);
6814				TALLOC_FREE(talloced);
6815				reply_nterror(req, NT_STATUS_NO_MEMORY);
6816				goto out;
6817			}
6818
6819			TALLOC_FREE(smb_fname_dst->base_name);
6820			smb_fname_dst->base_name = destname;
6821
6822			status = check_name(conn, smb_fname_src->base_name);
6823			if (!NT_STATUS_IS_OK(status)) {
6824				TALLOC_FREE(dir_hnd);
6825				TALLOC_FREE(talloced);
6826				reply_nterror(req, status);
6827				goto out;
6828			}
6829
6830			status = check_name(conn, smb_fname_dst->base_name);
6831			if (!NT_STATUS_IS_OK(status)) {
6832				TALLOC_FREE(dir_hnd);
6833				TALLOC_FREE(talloced);
6834				reply_nterror(req, status);
6835				goto out;
6836			}
6837
6838			DEBUG(3,("reply_copy : doing copy on %s -> %s\n",
6839				smb_fname_src->base_name,
6840				smb_fname_dst->base_name));
6841
6842			status = copy_file(ctx, conn, smb_fname_src,
6843					   smb_fname_dst, ofun,	count,
6844					   target_is_directory);
6845			if (NT_STATUS_IS_OK(status)) {
6846				count++;
6847			}
6848
6849			TALLOC_FREE(talloced);
6850		}
6851		TALLOC_FREE(dir_hnd);
6852	}
6853
6854	if (count == 0) {
6855		reply_nterror(req, dos_to_ntstatus(ERRDOS, error));
6856		goto out;
6857	}
6858
6859	reply_outbuf(req, 1, 0);
6860	SSVAL(req->outbuf,smb_vwv0,count);
6861 out:
6862	TALLOC_FREE(smb_fname_src);
6863	TALLOC_FREE(smb_fname_dst);
6864	TALLOC_FREE(fname_src);
6865	TALLOC_FREE(fname_dst);
6866	TALLOC_FREE(fname_src_mask);
6867	TALLOC_FREE(fname_src_dir);
6868
6869	END_PROFILE(SMBcopy);
6870	return;
6871}
6872
6873#undef DBGC_CLASS
6874#define DBGC_CLASS DBGC_LOCKING
6875
6876/****************************************************************************
6877 Get a lock pid, dealing with large count requests.
6878****************************************************************************/
6879
6880uint32 get_lock_pid(const uint8_t *data, int data_offset,
6881		    bool large_file_format)
6882{
6883	if(!large_file_format)
6884		return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
6885	else
6886		return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
6887}
6888
6889/****************************************************************************
6890 Get a lock count, dealing with large count requests.
6891****************************************************************************/
6892
6893uint64_t get_lock_count(const uint8_t *data, int data_offset,
6894			bool large_file_format)
6895{
6896	uint64_t count = 0;
6897
6898	if(!large_file_format) {
6899		count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
6900	} else {
6901
6902#if defined(HAVE_LONGLONG)
6903		count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
6904			((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
6905#else /* HAVE_LONGLONG */
6906
6907		/*
6908		 * NT4.x seems to be broken in that it sends large file (64 bit)
6909		 * lockingX calls even if the CAP_LARGE_FILES was *not*
6910		 * negotiated. For boxes without large unsigned ints truncate the
6911		 * lock count by dropping the top 32 bits.
6912		 */
6913
6914		if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
6915			DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
6916				(unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
6917				(unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
6918				SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
6919		}
6920
6921		count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
6922#endif /* HAVE_LONGLONG */
6923	}
6924
6925	return count;
6926}
6927
6928#if !defined(HAVE_LONGLONG)
6929/****************************************************************************
6930 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
6931****************************************************************************/
6932
6933static uint32 map_lock_offset(uint32 high, uint32 low)
6934{
6935	unsigned int i;
6936	uint32 mask = 0;
6937	uint32 highcopy = high;
6938
6939	/*
6940	 * Try and find out how many significant bits there are in high.
6941	 */
6942
6943	for(i = 0; highcopy; i++)
6944		highcopy >>= 1;
6945
6946	/*
6947	 * We use 31 bits not 32 here as POSIX
6948	 * lock offsets may not be negative.
6949	 */
6950
6951	mask = (~0) << (31 - i);
6952
6953	if(low & mask)
6954		return 0; /* Fail. */
6955
6956	high <<= (31 - i);
6957
6958	return (high|low);
6959}
6960#endif /* !defined(HAVE_LONGLONG) */
6961
6962/****************************************************************************
6963 Get a lock offset, dealing with large offset requests.
6964****************************************************************************/
6965
6966uint64_t get_lock_offset(const uint8_t *data, int data_offset,
6967			 bool large_file_format, bool *err)
6968{
6969	uint64_t offset = 0;
6970
6971	*err = False;
6972
6973	if(!large_file_format) {
6974		offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
6975	} else {
6976
6977#if defined(HAVE_LONGLONG)
6978		offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
6979				((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
6980#else /* HAVE_LONGLONG */
6981
6982		/*
6983		 * NT4.x seems to be broken in that it sends large file (64 bit)
6984		 * lockingX calls even if the CAP_LARGE_FILES was *not*
6985		 * negotiated. For boxes without large unsigned ints mangle the
6986		 * lock offset by mapping the top 32 bits onto the lower 32.
6987		 */
6988
6989		if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
6990			uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
6991			uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
6992			uint32 new_low = 0;
6993
6994			if((new_low = map_lock_offset(high, low)) == 0) {
6995				*err = True;
6996				return (uint64_t)-1;
6997			}
6998
6999			DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
7000				(unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
7001			SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
7002			SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
7003		}
7004
7005		offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
7006#endif /* HAVE_LONGLONG */
7007	}
7008
7009	return offset;
7010}
7011
7012NTSTATUS smbd_do_locking(struct smb_request *req,
7013			 files_struct *fsp,
7014			 uint8_t type,
7015			 int32_t timeout,
7016			 uint16_t num_ulocks,
7017			 struct smbd_lock_element *ulocks,
7018			 uint16_t num_locks,
7019			 struct smbd_lock_element *locks,
7020			 bool *async)
7021{
7022	connection_struct *conn = req->conn;
7023	int i;
7024	NTSTATUS status = NT_STATUS_OK;
7025
7026	*async = false;
7027
7028	/* Data now points at the beginning of the list
7029	   of smb_unlkrng structs */
7030	for(i = 0; i < (int)num_ulocks; i++) {
7031		struct smbd_lock_element *e = &ulocks[i];
7032
7033		DEBUG(10,("smbd_do_locking: unlock start=%.0f, len=%.0f for "
7034			  "pid %u, file %s\n",
7035			  (double)e->offset,
7036			  (double)e->count,
7037			  (unsigned int)e->smbpid,
7038			  fsp_str_dbg(fsp)));
7039
7040		if (e->brltype != UNLOCK_LOCK) {
7041			/* this can only happen with SMB2 */
7042			return NT_STATUS_INVALID_PARAMETER;
7043		}
7044
7045		status = do_unlock(smbd_messaging_context(),
7046				fsp,
7047				e->smbpid,
7048				e->count,
7049				e->offset,
7050				WINDOWS_LOCK);
7051
7052		DEBUG(10, ("smbd_do_locking: unlock returned %s\n",
7053		    nt_errstr(status)));
7054
7055		if (!NT_STATUS_IS_OK(status)) {
7056			return status;
7057		}
7058	}
7059
7060	/* Setup the timeout in seconds. */
7061
7062	if (!lp_blocking_locks(SNUM(conn))) {
7063		timeout = 0;
7064	}
7065
7066	/* Data now points at the beginning of the list
7067	   of smb_lkrng structs */
7068
7069	for(i = 0; i < (int)num_locks; i++) {
7070		struct smbd_lock_element *e = &locks[i];
7071
7072		DEBUG(10,("smbd_do_locking: lock start=%.0f, len=%.0f for pid "
7073			  "%u, file %s timeout = %d\n",
7074			  (double)e->offset,
7075			  (double)e->count,
7076			  (unsigned int)e->smbpid,
7077			  fsp_str_dbg(fsp),
7078			  (int)timeout));
7079
7080		if (type & LOCKING_ANDX_CANCEL_LOCK) {
7081			struct blocking_lock_record *blr = NULL;
7082
7083			if (num_locks > 1) {
7084				/*
7085				 * MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
7086				 * if the lock vector contains one entry. When given mutliple cancel
7087				 * requests in a single PDU we expect the server to return an
7088				 * error. Windows servers seem to accept the request but only
7089				 * cancel the first lock.
7090				 * JRA - Do what Windows does (tm) :-).
7091				 */
7092
7093#if 0
7094				/* MS-CIFS (2.2.4.32.1) behavior. */
7095				return NT_STATUS_DOS(ERRDOS,
7096						ERRcancelviolation);
7097#else
7098				/* Windows behavior. */
7099				if (i != 0) {
7100					DEBUG(10,("smbd_do_locking: ignoring subsequent "
7101						"cancel request\n"));
7102					continue;
7103				}
7104#endif
7105			}
7106
7107			if (lp_blocking_locks(SNUM(conn))) {
7108
7109				/* Schedule a message to ourselves to
7110				   remove the blocking lock record and
7111				   return the right error. */
7112
7113				blr = blocking_lock_cancel(fsp,
7114						e->smbpid,
7115						e->offset,
7116						e->count,
7117						WINDOWS_LOCK,
7118						type,
7119						NT_STATUS_FILE_LOCK_CONFLICT);
7120				if (blr == NULL) {
7121					return NT_STATUS_DOS(
7122							ERRDOS,
7123							ERRcancelviolation);
7124				}
7125			}
7126			/* Remove a matching pending lock. */
7127			status = do_lock_cancel(fsp,
7128						e->smbpid,
7129						e->count,
7130						e->offset,
7131						WINDOWS_LOCK,
7132						blr);
7133		} else {
7134			bool blocking_lock = timeout ? true : false;
7135			bool defer_lock = false;
7136			struct byte_range_lock *br_lck;
7137			uint32_t block_smbpid;
7138
7139			br_lck = do_lock(smbd_messaging_context(),
7140					fsp,
7141					e->smbpid,
7142					e->count,
7143					e->offset,
7144					e->brltype,
7145					WINDOWS_LOCK,
7146					blocking_lock,
7147					&status,
7148					&block_smbpid,
7149					NULL);
7150
7151			if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7152				/* Windows internal resolution for blocking locks seems
7153				   to be about 200ms... Don't wait for less than that. JRA. */
7154				if (timeout != -1 && timeout < lp_lock_spin_time()) {
7155					timeout = lp_lock_spin_time();
7156				}
7157				defer_lock = true;
7158			}
7159
7160			/* If a lock sent with timeout of zero would fail, and
7161			 * this lock has been requested multiple times,
7162			 * according to brl_lock_failed() we convert this
7163			 * request to a blocking lock with a timeout of between
7164			 * 150 - 300 milliseconds.
7165			 *
7166			 * If lp_lock_spin_time() has been set to 0, we skip
7167			 * this blocking retry and fail immediately.
7168			 *
7169			 * Replacement for do_lock_spin(). JRA. */
7170
7171			if (br_lck && lp_blocking_locks(SNUM(conn)) &&
7172			    lp_lock_spin_time() && !blocking_lock &&
7173			    NT_STATUS_EQUAL((status),
7174				NT_STATUS_FILE_LOCK_CONFLICT))
7175			{
7176				defer_lock = true;
7177				timeout = lp_lock_spin_time();
7178			}
7179
7180			if (br_lck && defer_lock) {
7181				/*
7182				 * A blocking lock was requested. Package up
7183				 * this smb into a queued request and push it
7184				 * onto the blocking lock queue.
7185				 */
7186				if(push_blocking_lock_request(br_lck,
7187							req,
7188							fsp,
7189							timeout,
7190							i,
7191							e->smbpid,
7192							e->brltype,
7193							WINDOWS_LOCK,
7194							e->offset,
7195							e->count,
7196							block_smbpid)) {
7197					TALLOC_FREE(br_lck);
7198					*async = true;
7199					return NT_STATUS_OK;
7200				}
7201			}
7202
7203			TALLOC_FREE(br_lck);
7204		}
7205
7206		if (!NT_STATUS_IS_OK(status)) {
7207			break;
7208		}
7209	}
7210
7211	/* If any of the above locks failed, then we must unlock
7212	   all of the previous locks (X/Open spec). */
7213
7214	if (num_locks != 0 && !NT_STATUS_IS_OK(status)) {
7215
7216		if (type & LOCKING_ANDX_CANCEL_LOCK) {
7217			i = -1; /* we want to skip the for loop */
7218		}
7219
7220		/*
7221		 * Ensure we don't do a remove on the lock that just failed,
7222		 * as under POSIX rules, if we have a lock already there, we
7223		 * will delete it (and we shouldn't) .....
7224		 */
7225		for(i--; i >= 0; i--) {
7226			struct smbd_lock_element *e = &locks[i];
7227
7228			do_unlock(smbd_messaging_context(),
7229				fsp,
7230				e->smbpid,
7231				e->count,
7232				e->offset,
7233				WINDOWS_LOCK);
7234		}
7235		return status;
7236	}
7237
7238	DEBUG(3, ("smbd_do_locking: fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7239		  fsp->fnum, (unsigned int)type, num_locks, num_ulocks));
7240
7241	return NT_STATUS_OK;
7242}
7243
7244/****************************************************************************
7245 Reply to a lockingX request.
7246****************************************************************************/
7247
7248void reply_lockingX(struct smb_request *req)
7249{
7250	connection_struct *conn = req->conn;
7251	files_struct *fsp;
7252	unsigned char locktype;
7253	unsigned char oplocklevel;
7254	uint16 num_ulocks;
7255	uint16 num_locks;
7256	int32 lock_timeout;
7257	int i;
7258	const uint8_t *data;
7259	bool large_file_format;
7260	bool err;
7261	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
7262	struct smbd_lock_element *ulocks;
7263	struct smbd_lock_element *locks;
7264	bool async = false;
7265
7266	START_PROFILE(SMBlockingX);
7267
7268	if (req->wct < 8) {
7269		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7270		END_PROFILE(SMBlockingX);
7271		return;
7272	}
7273
7274	fsp = file_fsp(req, SVAL(req->vwv+2, 0));
7275	locktype = CVAL(req->vwv+3, 0);
7276	oplocklevel = CVAL(req->vwv+3, 1);
7277	num_ulocks = SVAL(req->vwv+6, 0);
7278	num_locks = SVAL(req->vwv+7, 0);
7279	lock_timeout = IVAL(req->vwv+4, 0);
7280	large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
7281
7282	if (!check_fsp(conn, req, fsp)) {
7283		END_PROFILE(SMBlockingX);
7284		return;
7285	}
7286
7287	data = req->buf;
7288
7289	if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
7290		/* we don't support these - and CANCEL_LOCK makes w2k
7291		   and XP reboot so I don't really want to be
7292		   compatible! (tridge) */
7293		reply_force_doserror(req, ERRDOS, ERRnoatomiclocks);
7294		END_PROFILE(SMBlockingX);
7295		return;
7296	}
7297
7298	/* Check if this is an oplock break on a file
7299	   we have granted an oplock on.
7300	*/
7301	if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
7302		/* Client can insist on breaking to none. */
7303		bool break_to_none = (oplocklevel == 0);
7304		bool result;
7305
7306		DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
7307			 "for fnum = %d\n", (unsigned int)oplocklevel,
7308			 fsp->fnum ));
7309
7310		/*
7311		 * Make sure we have granted an exclusive or batch oplock on
7312		 * this file.
7313		 */
7314
7315		if (fsp->oplock_type == 0) {
7316
7317			/* The Samba4 nbench simulator doesn't understand
7318			   the difference between break to level2 and break
7319			   to none from level2 - it sends oplock break
7320			   replies in both cases. Don't keep logging an error
7321			   message here - just ignore it. JRA. */
7322
7323			DEBUG(5,("reply_lockingX: Error : oplock break from "
7324				 "client for fnum = %d (oplock=%d) and no "
7325				 "oplock granted on this file (%s).\n",
7326				 fsp->fnum, fsp->oplock_type,
7327				 fsp_str_dbg(fsp)));
7328
7329			/* if this is a pure oplock break request then don't
7330			 * send a reply */
7331			if (num_locks == 0 && num_ulocks == 0) {
7332				END_PROFILE(SMBlockingX);
7333				return;
7334			} else {
7335				END_PROFILE(SMBlockingX);
7336				reply_nterror(req, NT_STATUS_FILE_LOCK_CONFLICT);
7337				return;
7338			}
7339		}
7340
7341		if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
7342		    (break_to_none)) {
7343			result = remove_oplock(fsp);
7344		} else {
7345			result = downgrade_oplock(fsp);
7346		}
7347
7348		if (!result) {
7349			DEBUG(0, ("reply_lockingX: error in removing "
7350				  "oplock on file %s\n", fsp_str_dbg(fsp)));
7351			/* Hmmm. Is this panic justified? */
7352			smb_panic("internal tdb error");
7353		}
7354
7355		reply_to_oplock_break_requests(fsp);
7356
7357		/* if this is a pure oplock break request then don't send a
7358		 * reply */
7359		if (num_locks == 0 && num_ulocks == 0) {
7360			/* Sanity check - ensure a pure oplock break is not a
7361			   chained request. */
7362			if(CVAL(req->vwv+0, 0) != 0xff)
7363				DEBUG(0,("reply_lockingX: Error : pure oplock "
7364					 "break is a chained %d request !\n",
7365					 (unsigned int)CVAL(req->vwv+0, 0)));
7366			END_PROFILE(SMBlockingX);
7367			return;
7368		}
7369	}
7370
7371	if (req->buflen <
7372	    (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
7373		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7374		END_PROFILE(SMBlockingX);
7375		return;
7376	}
7377
7378	ulocks = talloc_array(req, struct smbd_lock_element, num_ulocks);
7379	if (ulocks == NULL) {
7380		reply_nterror(req, NT_STATUS_NO_MEMORY);
7381		END_PROFILE(SMBlockingX);
7382		return;
7383	}
7384
7385	locks = talloc_array(req, struct smbd_lock_element, num_locks);
7386	if (locks == NULL) {
7387		reply_nterror(req, NT_STATUS_NO_MEMORY);
7388		END_PROFILE(SMBlockingX);
7389		return;
7390	}
7391
7392	/* Data now points at the beginning of the list
7393	   of smb_unlkrng structs */
7394	for(i = 0; i < (int)num_ulocks; i++) {
7395		ulocks[i].smbpid = get_lock_pid(data, i, large_file_format);
7396		ulocks[i].count = get_lock_count(data, i, large_file_format);
7397		ulocks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7398		ulocks[i].brltype = UNLOCK_LOCK;
7399
7400		/*
7401		 * There is no error code marked "stupid client bug".... :-).
7402		 */
7403		if(err) {
7404			reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7405			END_PROFILE(SMBlockingX);
7406			return;
7407		}
7408	}
7409
7410	/* Now do any requested locks */
7411	data += ((large_file_format ? 20 : 10)*num_ulocks);
7412
7413	/* Data now points at the beginning of the list
7414	   of smb_lkrng structs */
7415
7416	for(i = 0; i < (int)num_locks; i++) {
7417		locks[i].smbpid = get_lock_pid(data, i, large_file_format);
7418		locks[i].count = get_lock_count(data, i, large_file_format);
7419		locks[i].offset = get_lock_offset(data, i, large_file_format, &err);
7420
7421		if (locktype & LOCKING_ANDX_SHARED_LOCK) {
7422			if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7423				locks[i].brltype = PENDING_READ_LOCK;
7424			} else {
7425				locks[i].brltype = READ_LOCK;
7426			}
7427		} else {
7428			if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
7429				locks[i].brltype = PENDING_WRITE_LOCK;
7430			} else {
7431				locks[i].brltype = WRITE_LOCK;
7432			}
7433		}
7434
7435		/*
7436		 * There is no error code marked "stupid client bug".... :-).
7437		 */
7438		if(err) {
7439			reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7440			END_PROFILE(SMBlockingX);
7441			return;
7442		}
7443	}
7444
7445	status = smbd_do_locking(req, fsp,
7446				 locktype, lock_timeout,
7447				 num_ulocks, ulocks,
7448				 num_locks, locks,
7449				 &async);
7450	if (!NT_STATUS_IS_OK(status)) {
7451		END_PROFILE(SMBlockingX);
7452		reply_nterror(req, status);
7453		return;
7454	}
7455	if (async) {
7456		END_PROFILE(SMBlockingX);
7457		return;
7458	}
7459
7460	reply_outbuf(req, 2, 0);
7461
7462	DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
7463		  fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
7464
7465	END_PROFILE(SMBlockingX);
7466	chain_reply(req);
7467}
7468
7469#undef DBGC_CLASS
7470#define DBGC_CLASS DBGC_ALL
7471
7472/****************************************************************************
7473 Reply to a SMBreadbmpx (read block multiplex) request.
7474 Always reply with an error, if someone has a platform really needs this,
7475 please contact vl@samba.org
7476****************************************************************************/
7477
7478void reply_readbmpx(struct smb_request *req)
7479{
7480	START_PROFILE(SMBreadBmpx);
7481	reply_force_doserror(req, ERRSRV, ERRuseSTD);
7482	END_PROFILE(SMBreadBmpx);
7483	return;
7484}
7485
7486/****************************************************************************
7487 Reply to a SMBreadbs (read block multiplex secondary) request.
7488 Always reply with an error, if someone has a platform really needs this,
7489 please contact vl@samba.org
7490****************************************************************************/
7491
7492void reply_readbs(struct smb_request *req)
7493{
7494	START_PROFILE(SMBreadBs);
7495	reply_force_doserror(req, ERRSRV, ERRuseSTD);
7496	END_PROFILE(SMBreadBs);
7497	return;
7498}
7499
7500/****************************************************************************
7501 Reply to a SMBsetattrE.
7502****************************************************************************/
7503
7504void reply_setattrE(struct smb_request *req)
7505{
7506	connection_struct *conn = req->conn;
7507	struct smb_file_time ft;
7508	files_struct *fsp;
7509	NTSTATUS status;
7510
7511	START_PROFILE(SMBsetattrE);
7512	ZERO_STRUCT(ft);
7513
7514	if (req->wct < 7) {
7515		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7516		goto out;
7517	}
7518
7519	fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7520
7521	if(!fsp || (fsp->conn != conn)) {
7522		reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7523		goto out;
7524	}
7525
7526	/*
7527	 * Convert the DOS times into unix times.
7528	 */
7529
7530	ft.atime = convert_time_t_to_timespec(
7531	    srv_make_unix_date2(req->vwv+3));
7532	ft.mtime = convert_time_t_to_timespec(
7533	    srv_make_unix_date2(req->vwv+5));
7534	ft.create_time = convert_time_t_to_timespec(
7535	    srv_make_unix_date2(req->vwv+1));
7536
7537	reply_outbuf(req, 0, 0);
7538
7539	/*
7540	 * Patch from Ray Frush <frush@engr.colostate.edu>
7541	 * Sometimes times are sent as zero - ignore them.
7542	 */
7543
7544	/* Ensure we have a valid stat struct for the source. */
7545	status = vfs_stat_fsp(fsp);
7546	if (!NT_STATUS_IS_OK(status)) {
7547		reply_nterror(req, status);
7548		goto out;
7549	}
7550
7551	status = smb_set_file_time(conn, fsp, fsp->fsp_name, &ft, true);
7552	if (!NT_STATUS_IS_OK(status)) {
7553		reply_nterror(req, status);
7554		goto out;
7555	}
7556
7557	DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u "
7558	       " createtime=%u\n",
7559		fsp->fnum,
7560		(unsigned int)ft.atime.tv_sec,
7561		(unsigned int)ft.mtime.tv_sec,
7562		(unsigned int)ft.create_time.tv_sec
7563		));
7564 out:
7565	END_PROFILE(SMBsetattrE);
7566	return;
7567}
7568
7569
7570/* Back from the dead for OS/2..... JRA. */
7571
7572/****************************************************************************
7573 Reply to a SMBwritebmpx (write block multiplex primary) request.
7574 Always reply with an error, if someone has a platform really needs this,
7575 please contact vl@samba.org
7576****************************************************************************/
7577
7578void reply_writebmpx(struct smb_request *req)
7579{
7580	START_PROFILE(SMBwriteBmpx);
7581	reply_force_doserror(req, ERRSRV, ERRuseSTD);
7582	END_PROFILE(SMBwriteBmpx);
7583	return;
7584}
7585
7586/****************************************************************************
7587 Reply to a SMBwritebs (write block multiplex secondary) request.
7588 Always reply with an error, if someone has a platform really needs this,
7589 please contact vl@samba.org
7590****************************************************************************/
7591
7592void reply_writebs(struct smb_request *req)
7593{
7594	START_PROFILE(SMBwriteBs);
7595	reply_force_doserror(req, ERRSRV, ERRuseSTD);
7596	END_PROFILE(SMBwriteBs);
7597	return;
7598}
7599
7600/****************************************************************************
7601 Reply to a SMBgetattrE.
7602****************************************************************************/
7603
7604void reply_getattrE(struct smb_request *req)
7605{
7606	connection_struct *conn = req->conn;
7607	int mode;
7608	files_struct *fsp;
7609	struct timespec create_ts;
7610
7611	START_PROFILE(SMBgetattrE);
7612
7613	if (req->wct < 1) {
7614		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7615		END_PROFILE(SMBgetattrE);
7616		return;
7617	}
7618
7619	fsp = file_fsp(req, SVAL(req->vwv+0, 0));
7620
7621	if(!fsp || (fsp->conn != conn)) {
7622		reply_nterror(req, NT_STATUS_INVALID_HANDLE);
7623		END_PROFILE(SMBgetattrE);
7624		return;
7625	}
7626
7627	/* Do an fstat on this file */
7628	if(fsp_stat(fsp)) {
7629		reply_nterror(req, map_nt_error_from_unix(errno));
7630		END_PROFILE(SMBgetattrE);
7631		return;
7632	}
7633
7634	mode = dos_mode(conn, fsp->fsp_name);
7635
7636	/*
7637	 * Convert the times into dos times. Set create
7638	 * date to be last modify date as UNIX doesn't save
7639	 * this.
7640	 */
7641
7642	reply_outbuf(req, 11, 0);
7643
7644	create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
7645	srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
7646	srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
7647			  convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_atime));
7648	/* Should we check pending modtime here ? JRA */
7649	srv_put_dos_date2((char *)req->outbuf, smb_vwv4,
7650			  convert_timespec_to_time_t(fsp->fsp_name->st.st_ex_mtime));
7651
7652	if (mode & aDIR) {
7653		SIVAL(req->outbuf, smb_vwv6, 0);
7654		SIVAL(req->outbuf, smb_vwv8, 0);
7655	} else {
7656		uint32 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp, &fsp->fsp_name->st);
7657		SIVAL(req->outbuf, smb_vwv6, (uint32)fsp->fsp_name->st.st_ex_size);
7658		SIVAL(req->outbuf, smb_vwv8, allocation_size);
7659	}
7660	SSVAL(req->outbuf,smb_vwv10, mode);
7661
7662	DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
7663
7664	END_PROFILE(SMBgetattrE);
7665	return;
7666}
7667