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
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 2 of the License, or
11   (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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
29/* look in server.c for some explanation of these variables */
30extern enum protocol_types Protocol;
31extern int max_send;
32extern int max_recv;
33unsigned int smb_echo_count = 0;
34extern uint32 global_client_caps;
35
36extern struct current_user current_user;
37extern BOOL global_encrypted_passwords_negotiated;
38
39/****************************************************************************
40 Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
41 path or anything including wildcards.
42 We're assuming here that '/' is not the second byte in any multibyte char
43 set (a safe assumption). '\\' *may* be the second byte in a multibyte char
44 set.
45****************************************************************************/
46
47/* Custom version for processing POSIX paths. */
48#define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
49
50NTSTATUS check_path_syntax_internal(pstring destname,
51				    const pstring srcname,
52				    BOOL posix_path,
53				    BOOL *p_last_component_contains_wcard)
54{
55	char *d = destname;
56	const char *s = srcname;
57	NTSTATUS ret = NT_STATUS_OK;
58	BOOL start_of_name_component = True;
59
60	*p_last_component_contains_wcard = False;
61
62	while (*s) {
63		if (IS_PATH_SEP(*s,posix_path)) {
64			/*
65			 * Safe to assume is not the second part of a mb char as this is handled below.
66			 */
67			/* Eat multiple '/' or '\\' */
68			while (IS_PATH_SEP(*s,posix_path)) {
69				s++;
70			}
71			if ((d != destname) && (*s != '\0')) {
72				/* We only care about non-leading or trailing '/' or '\\' */
73				*d++ = '/';
74			}
75
76			start_of_name_component = True;
77			/* New component. */
78			*p_last_component_contains_wcard = False;
79			continue;
80		}
81
82		if (start_of_name_component) {
83			if ((s[0] == '.') && (s[1] == '.') && (IS_PATH_SEP(s[2],posix_path) || s[2] == '\0')) {
84				/* Uh oh - "/../" or "\\..\\"  or "/..\0" or "\\..\0" ! */
85
86				/*
87				 * No mb char starts with '.' so we're safe checking the directory separator here.
88				 */
89
90				/* If  we just added a '/' - delete it */
91				if ((d > destname) && (*(d-1) == '/')) {
92					*(d-1) = '\0';
93					d--;
94				}
95
96				/* Are we at the start ? Can't go back further if so. */
97				if (d <= destname) {
98					ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
99					break;
100				}
101				/* Go back one level... */
102				/* We know this is safe as '/' cannot be part of a mb sequence. */
103				/* NOTE - if this assumption is invalid we are not in good shape... */
104				/* Decrement d first as d points to the *next* char to write into. */
105				for (d--; d > destname; d--) {
106					if (*d == '/')
107						break;
108				}
109				s += 2; /* Else go past the .. */
110				/* We're still at the start of a name component, just the previous one. */
111				continue;
112
113			} else if ((s[0] == '.') && ((s[1] == '\0') || IS_PATH_SEP(s[1],posix_path))) {
114				if (posix_path) {
115					/* Eat the '.' */
116					s++;
117					continue;
118				}
119			}
120
121		}
122
123		if (!(*s & 0x80)) {
124			if (!posix_path) {
125				if (*s <= 0x1f) {
126					return NT_STATUS_OBJECT_NAME_INVALID;
127				}
128				switch (*s) {
129					case '*':
130					case '?':
131					case '<':
132					case '>':
133					case '"':
134						*p_last_component_contains_wcard = True;
135						break;
136					default:
137						break;
138				}
139			}
140			*d++ = *s++;
141		} else {
142			size_t siz;
143			/* Get the size of the next MB character. */
144			next_codepoint(s,&siz);
145			switch(siz) {
146				case 5:
147					*d++ = *s++;
148					/*fall through*/
149				case 4:
150					*d++ = *s++;
151					/*fall through*/
152				case 3:
153					*d++ = *s++;
154					/*fall through*/
155				case 2:
156					*d++ = *s++;
157					/*fall through*/
158				case 1:
159					*d++ = *s++;
160					break;
161				default:
162					DEBUG(0,("check_path_syntax_internal: character length assumptions invalid !\n"));
163					*d = '\0';
164					return NT_STATUS_INVALID_PARAMETER;
165			}
166		}
167		start_of_name_component = False;
168	}
169
170	*d = '\0';
171	return ret;
172}
173
174/****************************************************************************
175 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
176 No wildcards allowed.
177****************************************************************************/
178
179NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
180{
181	BOOL ignore;
182	return check_path_syntax_internal(destname, srcname, False, &ignore);
183}
184
185/****************************************************************************
186 Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
187 Wildcards allowed - p_contains_wcard returns true if the last component contained
188 a wildcard.
189****************************************************************************/
190
191NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL *p_contains_wcard)
192{
193	return check_path_syntax_internal(destname, srcname, False, p_contains_wcard);
194}
195
196/****************************************************************************
197 Check the path for a POSIX client.
198 We're assuming here that '/' is not the second byte in any multibyte char
199 set (a safe assumption).
200****************************************************************************/
201
202NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname)
203{
204	BOOL ignore;
205	return check_path_syntax_internal(destname, srcname, True, &ignore);
206}
207
208/****************************************************************************
209 Pull a string and check the path allowing a wilcard - provide for error return.
210****************************************************************************/
211
212size_t srvstr_get_path_wcard(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags,
213				NTSTATUS *err, BOOL *contains_wcard)
214{
215	pstring tmppath;
216	char *tmppath_ptr = tmppath;
217	size_t ret;
218#ifdef DEVELOPER
219	SMB_ASSERT(dest_len == sizeof(pstring));
220#endif
221
222	if (src_len == 0) {
223		ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
224	} else {
225		ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
226	}
227
228	*contains_wcard = False;
229
230	if (SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) {
231		/*
232		 * For a DFS path the function parse_dfs_path()
233		 * will do the path processing, just make a copy.
234		 */
235		pstrcpy(dest, tmppath);
236		*err = NT_STATUS_OK;
237		return ret;
238	}
239
240	if (lp_posix_pathnames()) {
241		*err = check_path_syntax_posix(dest, tmppath);
242	} else {
243		*err = check_path_syntax_wcard(dest, tmppath, contains_wcard);
244	}
245
246	return ret;
247}
248
249/****************************************************************************
250 Pull a string and check the path - provide for error return.
251****************************************************************************/
252
253size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err)
254{
255	pstring tmppath;
256	char *tmppath_ptr = tmppath;
257	size_t ret;
258#ifdef DEVELOPER
259	SMB_ASSERT(dest_len == sizeof(pstring));
260#endif
261
262	if (src_len == 0) {
263		ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
264	} else {
265		ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
266	}
267
268	if (SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) {
269		/*
270		 * For a DFS path the function parse_dfs_path()
271		 * will do the path processing, just make a copy.
272		 */
273		pstrcpy(dest, tmppath);
274		*err = NT_STATUS_OK;
275		return ret;
276	}
277
278	if (lp_posix_pathnames()) {
279		*err = check_path_syntax_posix(dest, tmppath);
280	} else {
281		*err = check_path_syntax(dest, tmppath);
282	}
283
284	return ret;
285}
286
287/****************************************************************************
288 Reply to a special message.
289****************************************************************************/
290
291int reply_special(char *inbuf,char *outbuf)
292{
293	int outsize = 4;
294	int msg_type = CVAL(inbuf,0);
295	int msg_flags = CVAL(inbuf,1);
296	fstring name1,name2;
297	char name_type = 0;
298
299	static BOOL already_got_session = False;
300
301	*name1 = *name2 = 0;
302
303	memset(outbuf,'\0',smb_size);
304
305	smb_setlen(outbuf,0);
306
307	switch (msg_type) {
308	case 0x81: /* session request */
309
310		if (already_got_session) {
311			exit_server_cleanly("multiple session request not permitted");
312		}
313
314		SCVAL(outbuf,0,0x82);
315		SCVAL(outbuf,3,0);
316		if (name_len(inbuf+4) > 50 ||
317		    name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
318			DEBUG(0,("Invalid name length in session request\n"));
319			return(0);
320		}
321		name_extract(inbuf,4,name1);
322		name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
323		DEBUG(2,("netbios connect: name1=%s name2=%s\n",
324			 name1,name2));
325
326		set_local_machine_name(name1, True);
327		set_remote_machine_name(name2, True);
328
329		DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
330			 get_local_machine_name(), get_remote_machine_name(),
331			 name_type));
332
333		if (name_type == 'R') {
334			/* We are being asked for a pathworks session ---
335			   no thanks! */
336			SCVAL(outbuf, 0,0x83);
337			break;
338		}
339
340		/* only add the client's machine name to the list
341		   of possibly valid usernames if we are operating
342		   in share mode security */
343		if (lp_security() == SEC_SHARE) {
344			add_session_user(get_remote_machine_name());
345		}
346
347		reload_services(True);
348		reopen_logs();
349
350		already_got_session = True;
351		break;
352
353	case 0x89: /* session keepalive request
354		      (some old clients produce this?) */
355		SCVAL(outbuf,0,SMBkeepalive);
356		SCVAL(outbuf,3,0);
357		break;
358
359	case 0x82: /* positive session response */
360	case 0x83: /* negative session response */
361	case 0x84: /* retarget session response */
362		DEBUG(0,("Unexpected session response\n"));
363		break;
364
365	case SMBkeepalive: /* session keepalive */
366	default:
367		return(0);
368	}
369
370	DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
371		    msg_type, msg_flags));
372
373	return(outsize);
374}
375
376/****************************************************************************
377 Reply to a tcon.
378 conn POINTER CAN BE NULL HERE !
379****************************************************************************/
380
381int reply_tcon(connection_struct *conn,
382	       char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
383{
384	const char *service;
385	pstring service_buf;
386	pstring password;
387	pstring dev;
388	int outsize = 0;
389	uint16 vuid = SVAL(inbuf,smb_uid);
390	int pwlen=0;
391	NTSTATUS nt_status;
392	char *p;
393	DATA_BLOB password_blob;
394
395	START_PROFILE(SMBtcon);
396
397	*service_buf = *password = *dev = 0;
398
399	p = smb_buf(inbuf)+1;
400	p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
401	pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
402	p += pwlen;
403	p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
404
405	p = strrchr_m(service_buf,'\\');
406	if (p) {
407		service = p+1;
408	} else {
409		service = service_buf;
410	}
411
412	password_blob = data_blob(password, pwlen+1);
413
414	conn = make_connection(service,password_blob,dev,vuid,&nt_status);
415
416	data_blob_clear_free(&password_blob);
417
418	if (!conn) {
419		END_PROFILE(SMBtcon);
420		return ERROR_NT(nt_status);
421	}
422
423	outsize = set_message(outbuf,2,0,True);
424	SSVAL(outbuf,smb_vwv0,max_recv);
425	SSVAL(outbuf,smb_vwv1,conn->cnum);
426	SSVAL(outbuf,smb_tid,conn->cnum);
427
428	DEBUG(3,("tcon service=%s cnum=%d\n",
429		 service, conn->cnum));
430
431	END_PROFILE(SMBtcon);
432	return(outsize);
433}
434
435/****************************************************************************
436 Reply to a tcon and X.
437 conn POINTER CAN BE NULL HERE !
438****************************************************************************/
439
440int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
441{
442	fstring service;
443	DATA_BLOB password;
444
445	/* what the cleint thinks the device is */
446	fstring client_devicetype;
447	/* what the server tells the client the share represents */
448	const char *server_devicetype;
449	NTSTATUS nt_status;
450	uint16 vuid = SVAL(inbuf,smb_uid);
451	int passlen = SVAL(inbuf,smb_vwv3);
452	pstring path;
453	char *p, *q;
454	uint16 tcon_flags = SVAL(inbuf,smb_vwv2);
455
456	START_PROFILE(SMBtconX);
457
458	*service = *client_devicetype = 0;
459
460	/* we might have to close an old one */
461	if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
462		close_cnum(conn,vuid);
463	}
464
465	if (passlen > MAX_PASS_LEN) {
466		return ERROR_DOS(ERRDOS,ERRbuftoosmall);
467	}
468
469	if (global_encrypted_passwords_negotiated) {
470		password = data_blob(smb_buf(inbuf),passlen);
471		if (lp_security() == SEC_SHARE) {
472			/*
473			 * Security = share always has a pad byte
474			 * after the password.
475			 */
476			p = smb_buf(inbuf) + passlen + 1;
477		} else {
478			p = smb_buf(inbuf) + passlen;
479		}
480	} else {
481		password = data_blob(smb_buf(inbuf),passlen+1);
482		/* Ensure correct termination */
483		password.data[passlen]=0;
484		p = smb_buf(inbuf) + passlen + 1;
485	}
486
487	p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
488
489	/*
490	 * the service name can be either: \\server\share
491	 * or share directly like on the DELL PowerVault 705
492	 */
493	if (*path=='\\') {
494		q = strchr_m(path+2,'\\');
495		if (!q) {
496			END_PROFILE(SMBtconX);
497			return(ERROR_DOS(ERRDOS,ERRnosuchshare));
498		}
499		fstrcpy(service,q+1);
500	}
501	else
502		fstrcpy(service,path);
503
504	p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
505
506	DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
507
508	conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
509
510	data_blob_clear_free(&password);
511
512	if (!conn) {
513		END_PROFILE(SMBtconX);
514		return ERROR_NT(nt_status);
515	}
516
517	if ( IS_IPC(conn) )
518		server_devicetype = "IPC";
519	else if ( IS_PRINT(conn) )
520		server_devicetype = "LPT1:";
521	else
522		server_devicetype = "A:";
523
524	if (Protocol < PROTOCOL_NT1) {
525		set_message(outbuf,2,0,True);
526		p = smb_buf(outbuf);
527		p += srvstr_push(outbuf, p, server_devicetype, -1,
528				 STR_TERMINATE|STR_ASCII);
529		set_message_end(outbuf,p);
530	} else {
531		/* NT sets the fstype of IPC$ to the null string */
532		const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
533
534		if (tcon_flags & TCONX_FLAG_EXTENDED_RESPONSE) {
535			/* Return permissions. */
536			uint32 perm1 = 0;
537			uint32 perm2 = 0;
538
539			set_message(outbuf,7,0,True);
540
541			if (IS_IPC(conn)) {
542				perm1 = FILE_ALL_ACCESS;
543				perm2 = FILE_ALL_ACCESS;
544			} else {
545				perm1 = CAN_WRITE(conn) ?
546						SHARE_ALL_ACCESS :
547						SHARE_READ_ONLY;
548			}
549
550			SIVAL(outbuf, smb_vwv3, perm1);
551			SIVAL(outbuf, smb_vwv5, perm2);
552		} else {
553			set_message(outbuf,3,0,True);
554		}
555
556		p = smb_buf(outbuf);
557		p += srvstr_push(outbuf, p, server_devicetype, -1,
558				 STR_TERMINATE|STR_ASCII);
559		p += srvstr_push(outbuf, p, fstype, -1,
560				 STR_TERMINATE);
561
562		set_message_end(outbuf,p);
563
564		/* what does setting this bit do? It is set by NT4 and
565		   may affect the ability to autorun mounted cdroms */
566		SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
567				(lp_csc_policy(SNUM(conn)) << 2));
568
569		init_dfsroot(conn, inbuf, outbuf);
570	}
571
572
573	DEBUG(3,("tconX service=%s \n",
574		 service));
575
576	/* set the incoming and outgoing tid to the just created one */
577	SSVAL(inbuf,smb_tid,conn->cnum);
578	SSVAL(outbuf,smb_tid,conn->cnum);
579
580	END_PROFILE(SMBtconX);
581	return chain_reply(inbuf,outbuf,length,bufsize);
582}
583
584/****************************************************************************
585 Reply to an unknown type.
586****************************************************************************/
587
588int reply_unknown(char *inbuf,char *outbuf)
589{
590	int type;
591	type = CVAL(inbuf,smb_com);
592
593	DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
594		 smb_fn_name(type), type, type));
595
596	return(ERROR_DOS(ERRSRV,ERRunknownsmb));
597}
598
599/****************************************************************************
600 Reply to an ioctl.
601 conn POINTER CAN BE NULL HERE !
602****************************************************************************/
603
604int reply_ioctl(connection_struct *conn,
605		char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
606{
607	uint16 device     = SVAL(inbuf,smb_vwv1);
608	uint16 function   = SVAL(inbuf,smb_vwv2);
609	uint32 ioctl_code = (device << 16) + function;
610	int replysize, outsize;
611	char *p;
612	START_PROFILE(SMBioctl);
613
614	DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
615
616	switch (ioctl_code) {
617	    case IOCTL_QUERY_JOB_INFO:
618		replysize = 32;
619		break;
620	    default:
621		END_PROFILE(SMBioctl);
622		return(ERROR_DOS(ERRSRV,ERRnosupport));
623	}
624
625	outsize = set_message(outbuf,8,replysize+1,True);
626	SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
627	SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
628	SSVAL(outbuf,smb_vwv6,52);        /* Offset to data */
629	p = smb_buf(outbuf) + 1;          /* Allow for alignment */
630
631	switch (ioctl_code) {
632		case IOCTL_QUERY_JOB_INFO:
633		{
634			files_struct *fsp = file_fsp(inbuf,smb_vwv0);
635			if (!fsp) {
636				END_PROFILE(SMBioctl);
637				return(UNIXERROR(ERRDOS,ERRbadfid));
638			}
639			SSVAL(p,0,fsp->rap_print_jobid);             /* Job number */
640			srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
641			if (conn) {
642				srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
643			}
644			break;
645		}
646	}
647
648	END_PROFILE(SMBioctl);
649	return outsize;
650}
651
652/****************************************************************************
653 Strange checkpath NTSTATUS mapping.
654****************************************************************************/
655
656static NTSTATUS map_checkpath_error(const char *inbuf, NTSTATUS status)
657{
658	/* Strange DOS error code semantics only for checkpath... */
659	if (!(SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) {
660		if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
661			/* We need to map to ERRbadpath */
662			return NT_STATUS_OBJECT_PATH_NOT_FOUND;
663		}
664	}
665	return status;
666}
667
668/****************************************************************************
669 Reply to a checkpath.
670****************************************************************************/
671
672int reply_checkpath(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
673{
674	int outsize = 0;
675	pstring name;
676	SMB_STRUCT_STAT sbuf;
677	NTSTATUS status;
678
679	START_PROFILE(SMBcheckpath);
680
681	srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
682	if (!NT_STATUS_IS_OK(status)) {
683		END_PROFILE(SMBcheckpath);
684		status = map_checkpath_error(inbuf, status);
685		return ERROR_NT(status);
686	}
687
688	status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name);
689	if (!NT_STATUS_IS_OK(status)) {
690		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
691			END_PROFILE(SMBcheckpath);
692			return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
693		}
694		goto path_err;
695	}
696
697	DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0)));
698
699	status = unix_convert(conn, name, False, NULL, &sbuf);
700	if (!NT_STATUS_IS_OK(status)) {
701		goto path_err;
702	}
703
704	status = check_name(conn, name);
705	if (!NT_STATUS_IS_OK(status)) {
706		DEBUG(3,("reply_checkpath: check_name of %s failed (%s)\n",name,nt_errstr(status)));
707		goto path_err;
708	}
709
710	if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,name,&sbuf) != 0)) {
711		DEBUG(3,("reply_checkpath: stat of %s failed (%s)\n",name,strerror(errno)));
712		status = map_nt_error_from_unix(errno);
713		goto path_err;
714	}
715
716	if (!S_ISDIR(sbuf.st_mode)) {
717		END_PROFILE(SMBcheckpath);
718		return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
719	}
720
721	outsize = set_message(outbuf,0,0,False);
722
723	END_PROFILE(SMBcheckpath);
724	return outsize;
725
726  path_err:
727
728	END_PROFILE(SMBcheckpath);
729
730	/* We special case this - as when a Windows machine
731		is parsing a path is steps through the components
732		one at a time - if a component fails it expects
733		ERRbadpath, not ERRbadfile.
734	*/
735	status = map_checkpath_error(inbuf, status);
736	if(NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
737		/*
738		 * Windows returns different error codes if
739		 * the parent directory is valid but not the
740		 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
741		 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
742		 * if the path is invalid.
743		 */
744		return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
745	}
746
747	return ERROR_NT(status);
748}
749
750/****************************************************************************
751 Reply to a getatr.
752****************************************************************************/
753
754int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
755{
756	pstring fname;
757	int outsize = 0;
758	SMB_STRUCT_STAT sbuf;
759	int mode=0;
760	SMB_OFF_T size=0;
761	time_t mtime=0;
762	char *p;
763	NTSTATUS status;
764
765	START_PROFILE(SMBgetatr);
766
767	p = smb_buf(inbuf) + 1;
768	p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
769	if (!NT_STATUS_IS_OK(status)) {
770		END_PROFILE(SMBgetatr);
771		return ERROR_NT(status);
772	}
773
774	status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
775	if (!NT_STATUS_IS_OK(status)) {
776		END_PROFILE(SMBgetatr);
777		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
778			return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
779		}
780		return ERROR_NT(status);
781	}
782
783	/* dos smetimes asks for a stat of "" - it returns a "hidden directory"
784		under WfWg - weird! */
785	if (*fname == '\0') {
786		mode = aHIDDEN | aDIR;
787		if (!CAN_WRITE(conn)) {
788			mode |= aRONLY;
789		}
790		size = 0;
791		mtime = 0;
792	} else {
793		status = unix_convert(conn, fname, False, NULL,&sbuf);
794		if (!NT_STATUS_IS_OK(status)) {
795			END_PROFILE(SMBgetatr);
796			return ERROR_NT(status);
797		}
798		status = check_name(conn, fname);
799		if (!NT_STATUS_IS_OK(status)) {
800			DEBUG(3,("reply_getatr: check_name of %s failed (%s)\n",fname,nt_errstr(status)));
801			END_PROFILE(SMBgetatr);
802			return ERROR_NT(status);
803		}
804		if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn,fname,&sbuf) != 0)) {
805			DEBUG(3,("reply_getatr: stat of %s failed (%s)\n",fname,strerror(errno)));
806			return UNIXERROR(ERRDOS,ERRbadfile);
807		}
808
809		mode = dos_mode(conn,fname,&sbuf);
810		size = sbuf.st_size;
811		mtime = sbuf.st_mtime;
812		if (mode & aDIR) {
813			size = 0;
814		}
815	}
816
817	outsize = set_message(outbuf,10,0,True);
818
819	SSVAL(outbuf,smb_vwv0,mode);
820	if(lp_dos_filetime_resolution(SNUM(conn)) ) {
821		srv_put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
822	} else {
823		srv_put_dos_date3(outbuf,smb_vwv1,mtime);
824	}
825	SIVAL(outbuf,smb_vwv3,(uint32)size);
826
827	if (Protocol >= PROTOCOL_NT1) {
828		SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
829	}
830
831	DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
832
833	END_PROFILE(SMBgetatr);
834	return(outsize);
835}
836
837/****************************************************************************
838 Reply to a setatr.
839****************************************************************************/
840
841int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
842{
843	pstring fname;
844	int outsize = 0;
845	int mode;
846	time_t mtime;
847	SMB_STRUCT_STAT sbuf;
848	char *p;
849	NTSTATUS status;
850
851	START_PROFILE(SMBsetatr);
852
853	p = smb_buf(inbuf) + 1;
854	p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
855	if (!NT_STATUS_IS_OK(status)) {
856		END_PROFILE(SMBsetatr);
857		return ERROR_NT(status);
858	}
859
860	status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
861	if (!NT_STATUS_IS_OK(status)) {
862		END_PROFILE(SMBsetatr);
863		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
864			return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
865		}
866		return ERROR_NT(status);
867	}
868
869	status = unix_convert(conn, fname, False, NULL, &sbuf);
870	if (!NT_STATUS_IS_OK(status)) {
871		END_PROFILE(SMBsetatr);
872		return ERROR_NT(status);
873	}
874
875	status = check_name(conn, fname);
876	if (!NT_STATUS_IS_OK(status)) {
877		END_PROFILE(SMBsetatr);
878		return ERROR_NT(status);
879	}
880
881	if (fname[0] == '.' && fname[1] == '\0') {
882		/*
883		 * Not sure here is the right place to catch this
884		 * condition. Might be moved to somewhere else later -- vl
885		 */
886		END_PROFILE(SMBsetatr);
887		return ERROR_NT(NT_STATUS_ACCESS_DENIED);
888	}
889
890	mode = SVAL(inbuf,smb_vwv0);
891	mtime = srv_make_unix_date3(inbuf+smb_vwv1);
892
893	if (mode != FILE_ATTRIBUTE_NORMAL) {
894		if (VALID_STAT_OF_DIR(sbuf))
895			mode |= aDIR;
896		else
897			mode &= ~aDIR;
898
899		if (file_set_dosmode(conn,fname,mode,&sbuf,False) != 0) {
900			END_PROFILE(SMBsetatr);
901			return UNIXERROR(ERRDOS, ERRnoaccess);
902		}
903	}
904
905	if (!set_filetime(conn,fname,convert_time_t_to_timespec(mtime))) {
906		END_PROFILE(SMBsetatr);
907		return UNIXERROR(ERRDOS, ERRnoaccess);
908	}
909
910	outsize = set_message(outbuf,0,0,False);
911
912	DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
913
914	END_PROFILE(SMBsetatr);
915	return(outsize);
916}
917
918/****************************************************************************
919 Reply to a dskattr.
920****************************************************************************/
921
922int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
923{
924	int outsize = 0;
925	SMB_BIG_UINT dfree,dsize,bsize;
926	START_PROFILE(SMBdskattr);
927
928	if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
929		END_PROFILE(SMBdskattr);
930		return(UNIXERROR(ERRHRD,ERRgeneral));
931	}
932
933	outsize = set_message(outbuf,5,0,True);
934
935	if (Protocol <= PROTOCOL_LANMAN2) {
936		double total_space, free_space;
937		/* we need to scale this to a number that DOS6 can handle. We
938		   use floating point so we can handle large drives on systems
939		   that don't have 64 bit integers
940
941		   we end up displaying a maximum of 2G to DOS systems
942		*/
943		total_space = dsize * (double)bsize;
944		free_space = dfree * (double)bsize;
945
946		dsize = (total_space+63*512) / (64*512);
947		dfree = (free_space+63*512) / (64*512);
948
949		if (dsize > 0xFFFF) dsize = 0xFFFF;
950		if (dfree > 0xFFFF) dfree = 0xFFFF;
951
952		SSVAL(outbuf,smb_vwv0,dsize);
953		SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
954		SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
955		SSVAL(outbuf,smb_vwv3,dfree);
956	} else {
957		SSVAL(outbuf,smb_vwv0,dsize);
958		SSVAL(outbuf,smb_vwv1,bsize/512);
959		SSVAL(outbuf,smb_vwv2,512);
960		SSVAL(outbuf,smb_vwv3,dfree);
961	}
962
963	DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
964
965	END_PROFILE(SMBdskattr);
966	return(outsize);
967}
968
969/****************************************************************************
970 Reply to a search.
971 Can be called from SMBsearch, SMBffirst or SMBfunique.
972****************************************************************************/
973
974int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
975{
976	pstring mask;
977	pstring directory;
978	pstring fname;
979	SMB_OFF_T size;
980	uint32 mode;
981	time_t date;
982	uint32 dirtype;
983	int outsize = 0;
984	unsigned int numentries = 0;
985	unsigned int maxentries = 0;
986	BOOL finished = False;
987	char *p;
988	int status_len;
989	pstring path;
990	char status[21];
991	int dptr_num= -1;
992	BOOL check_descend = False;
993	BOOL expect_close = False;
994	NTSTATUS nt_status;
995	BOOL mask_contains_wcard = False;
996	BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
997
998	START_PROFILE(SMBsearch);
999
1000	if (lp_posix_pathnames()) {
1001		END_PROFILE(SMBsearch);
1002		return reply_unknown(inbuf, outbuf);
1003	}
1004
1005	*mask = *directory = *fname = 0;
1006
1007	/* If we were called as SMBffirst then we must expect close. */
1008	if(CVAL(inbuf,smb_com) == SMBffirst) {
1009		expect_close = True;
1010	}
1011
1012	outsize = set_message(outbuf,1,3,True);
1013	maxentries = SVAL(inbuf,smb_vwv0);
1014	dirtype = SVAL(inbuf,smb_vwv1);
1015	p = smb_buf(inbuf) + 1;
1016	p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, &mask_contains_wcard);
1017	if (!NT_STATUS_IS_OK(nt_status)) {
1018		END_PROFILE(SMBsearch);
1019		return ERROR_NT(nt_status);
1020	}
1021
1022	nt_status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, path, &mask_contains_wcard);
1023	if (!NT_STATUS_IS_OK(nt_status)) {
1024		END_PROFILE(SMBsearch);
1025		if (NT_STATUS_EQUAL(nt_status,NT_STATUS_PATH_NOT_COVERED)) {
1026			return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1027		}
1028		return ERROR_NT(nt_status);
1029	}
1030
1031	p++;
1032	status_len = SVAL(p, 0);
1033	p += 2;
1034
1035	/* dirtype &= ~aDIR; */
1036
1037	if (status_len == 0) {
1038		SMB_STRUCT_STAT sbuf;
1039
1040		pstrcpy(directory,path);
1041		nt_status = unix_convert(conn, directory, True, NULL, &sbuf);
1042		if (!NT_STATUS_IS_OK(nt_status)) {
1043			END_PROFILE(SMBsearch);
1044			return ERROR_NT(nt_status);
1045		}
1046
1047		nt_status = check_name(conn, directory);
1048		if (!NT_STATUS_IS_OK(nt_status)) {
1049			END_PROFILE(SMBsearch);
1050			return ERROR_NT(nt_status);
1051		}
1052
1053		p = strrchr_m(directory,'/');
1054		if (!p) {
1055			pstrcpy(mask,directory);
1056			pstrcpy(directory,".");
1057		} else {
1058			*p = 0;
1059			pstrcpy(mask,p+1);
1060		}
1061
1062		if (*directory == '\0') {
1063			pstrcpy(directory,".");
1064		}
1065		memset((char *)status,'\0',21);
1066		SCVAL(status,0,(dirtype & 0x1F));
1067	} else {
1068		int status_dirtype;
1069
1070		memcpy(status,p,21);
1071		status_dirtype = CVAL(status,0) & 0x1F;
1072		if (status_dirtype != (dirtype & 0x1F)) {
1073			dirtype = status_dirtype;
1074		}
1075
1076		conn->dirptr = dptr_fetch(status+12,&dptr_num);
1077		if (!conn->dirptr) {
1078			goto SearchEmpty;
1079		}
1080		string_set(&conn->dirpath,dptr_path(dptr_num));
1081		pstrcpy(mask, dptr_wcard(dptr_num));
1082		/*
1083		 * For a 'continue' search we have no string. So
1084		 * check from the initial saved string.
1085		 */
1086		mask_contains_wcard = ms_has_wild(mask);
1087	}
1088
1089	p = smb_buf(outbuf) + 3;
1090
1091	if (status_len == 0) {
1092		nt_status = dptr_create(conn,
1093					directory,
1094					True,
1095					expect_close,
1096					SVAL(inbuf,smb_pid),
1097					mask,
1098					mask_contains_wcard,
1099					dirtype,
1100					&conn->dirptr);
1101		if (!NT_STATUS_IS_OK(nt_status)) {
1102			return ERROR_NT(nt_status);
1103		}
1104		dptr_num = dptr_dnum(conn->dirptr);
1105	} else {
1106		dirtype = dptr_attr(dptr_num);
1107	}
1108
1109	DEBUG(4,("dptr_num is %d\n",dptr_num));
1110
1111	if ((dirtype&0x1F) == aVOLID) {
1112		memcpy(p,status,21);
1113		make_dir_struct(p,"???????????",volume_label(SNUM(conn)),
1114				0,aVOLID,0,!allow_long_path_components);
1115		dptr_fill(p+12,dptr_num);
1116		if (dptr_zero(p+12) && (status_len==0)) {
1117			numentries = 1;
1118		} else {
1119			numentries = 0;
1120		}
1121		p += DIR_STRUCT_SIZE;
1122	} else {
1123		unsigned int i;
1124		maxentries = MIN(maxentries, ((BUFFER_SIZE - (p - outbuf))/DIR_STRUCT_SIZE));
1125
1126		DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
1127			conn->dirpath,lp_dontdescend(SNUM(conn))));
1128		if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True)) {
1129			check_descend = True;
1130		}
1131
1132		for (i=numentries;(i<maxentries) && !finished;i++) {
1133			finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
1134			if (!finished) {
1135				memcpy(p,status,21);
1136				make_dir_struct(p,mask,fname,size, mode,date,
1137						!allow_long_path_components);
1138				if (!dptr_fill(p+12,dptr_num)) {
1139					break;
1140				}
1141				numentries++;
1142				p += DIR_STRUCT_SIZE;
1143			}
1144		}
1145	}
1146
1147  SearchEmpty:
1148
1149	/* If we were called as SMBffirst with smb_search_id == NULL
1150		and no entries were found then return error and close dirptr
1151		(X/Open spec) */
1152
1153	if (numentries == 0) {
1154		dptr_close(&dptr_num);
1155	} else if(expect_close && status_len == 0) {
1156		/* Close the dptr - we know it's gone */
1157		dptr_close(&dptr_num);
1158	}
1159
1160	/* If we were called as SMBfunique, then we can close the dirptr now ! */
1161	if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) {
1162		dptr_close(&dptr_num);
1163	}
1164
1165	if ((numentries == 0) && !mask_contains_wcard) {
1166		return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
1167	}
1168
1169	SSVAL(outbuf,smb_vwv0,numentries);
1170	SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
1171	SCVAL(smb_buf(outbuf),0,5);
1172	SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
1173
1174	/* The replies here are never long name. */
1175	SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
1176	if (!allow_long_path_components) {
1177		SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_LONG_PATH_COMPONENTS));
1178	}
1179
1180	/* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
1181	SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
1182
1183	outsize += DIR_STRUCT_SIZE*numentries;
1184	smb_setlen(outbuf,outsize - 4);
1185
1186	if ((! *directory) && dptr_path(dptr_num))
1187		slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1188
1189	DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%u of %u\n",
1190		smb_fn_name(CVAL(inbuf,smb_com)),
1191		mask, directory, dirtype, numentries, maxentries ) );
1192
1193	END_PROFILE(SMBsearch);
1194	return(outsize);
1195}
1196
1197/****************************************************************************
1198 Reply to a fclose (stop directory search).
1199****************************************************************************/
1200
1201int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1202{
1203	int outsize = 0;
1204	int status_len;
1205	pstring path;
1206	char status[21];
1207	int dptr_num= -2;
1208	char *p;
1209	NTSTATUS err;
1210	BOOL path_contains_wcard = False;
1211
1212	START_PROFILE(SMBfclose);
1213
1214	if (lp_posix_pathnames()) {
1215		END_PROFILE(SMBfclose);
1216		return reply_unknown(inbuf, outbuf);
1217	}
1218
1219	outsize = set_message(outbuf,1,0,True);
1220	p = smb_buf(inbuf) + 1;
1221	p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, &path_contains_wcard);
1222	if (!NT_STATUS_IS_OK(err)) {
1223		END_PROFILE(SMBfclose);
1224		return ERROR_NT(err);
1225	}
1226	p++;
1227	status_len = SVAL(p,0);
1228	p += 2;
1229
1230	if (status_len == 0) {
1231		END_PROFILE(SMBfclose);
1232		return ERROR_DOS(ERRSRV,ERRsrverror);
1233	}
1234
1235	memcpy(status,p,21);
1236
1237	if(dptr_fetch(status+12,&dptr_num)) {
1238		/*  Close the dptr - we know it's gone */
1239		dptr_close(&dptr_num);
1240	}
1241
1242	SSVAL(outbuf,smb_vwv0,0);
1243
1244	DEBUG(3,("search close\n"));
1245
1246	END_PROFILE(SMBfclose);
1247	return(outsize);
1248}
1249
1250/****************************************************************************
1251 Reply to an open.
1252****************************************************************************/
1253
1254int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1255{
1256	pstring fname;
1257	int outsize = 0;
1258	uint32 fattr=0;
1259	SMB_OFF_T size = 0;
1260	time_t mtime=0;
1261	int info;
1262	SMB_STRUCT_STAT sbuf;
1263	files_struct *fsp;
1264	int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1265	int deny_mode;
1266	uint32 dos_attr = SVAL(inbuf,smb_vwv1);
1267	uint32 access_mask;
1268	uint32 share_mode;
1269	uint32 create_disposition;
1270	uint32 create_options = 0;
1271	NTSTATUS status;
1272	START_PROFILE(SMBopen);
1273
1274	deny_mode = SVAL(inbuf,smb_vwv0);
1275
1276	srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1277	if (!NT_STATUS_IS_OK(status)) {
1278		END_PROFILE(SMBopen);
1279		return ERROR_NT(status);
1280	}
1281
1282	status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1283	if (!NT_STATUS_IS_OK(status)) {
1284		END_PROFILE(SMBopen);
1285		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1286			return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1287		}
1288		return ERROR_NT(status);
1289	}
1290
1291	status = unix_convert(conn, fname, False, NULL, &sbuf);
1292	if (!NT_STATUS_IS_OK(status)) {
1293		END_PROFILE(SMBopen);
1294		return ERROR_NT(status);
1295	}
1296
1297	status = check_name(conn, fname);
1298	if (!NT_STATUS_IS_OK(status)) {
1299		END_PROFILE(SMBopen);
1300		return ERROR_NT(status);
1301	}
1302
1303	if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
1304			&access_mask, &share_mode, &create_disposition, &create_options)) {
1305		END_PROFILE(SMBopen);
1306		return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1307	}
1308
1309	status = open_file_ntcreate(conn,fname,&sbuf,
1310			access_mask,
1311			share_mode,
1312			create_disposition,
1313			create_options,
1314			dos_attr,
1315			oplock_request,
1316			&info, &fsp);
1317
1318	if (!NT_STATUS_IS_OK(status)) {
1319		END_PROFILE(SMBopen);
1320		if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1321			/* We have re-scheduled this call. */
1322			return -1;
1323		}
1324		return ERROR_NT(status);
1325	}
1326
1327	size = sbuf.st_size;
1328	fattr = dos_mode(conn,fname,&sbuf);
1329	mtime = sbuf.st_mtime;
1330
1331	if (fattr & aDIR) {
1332		DEBUG(3,("attempt to open a directory %s\n",fname));
1333		close_file(fsp,ERROR_CLOSE);
1334		END_PROFILE(SMBopen);
1335		return ERROR_DOS(ERRDOS,ERRnoaccess);
1336	}
1337
1338	outsize = set_message(outbuf,7,0,True);
1339	SSVAL(outbuf,smb_vwv0,fsp->fnum);
1340	SSVAL(outbuf,smb_vwv1,fattr);
1341	if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1342		srv_put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
1343	} else {
1344		srv_put_dos_date3(outbuf,smb_vwv2,mtime);
1345	}
1346	SIVAL(outbuf,smb_vwv4,(uint32)size);
1347	SSVAL(outbuf,smb_vwv6,deny_mode);
1348
1349	if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1350		SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1351	}
1352
1353	if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1354		SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1355	}
1356	END_PROFILE(SMBopen);
1357	return(outsize);
1358}
1359
1360/****************************************************************************
1361 Reply to an open and X.
1362****************************************************************************/
1363
1364int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1365{
1366	pstring fname;
1367	uint16 open_flags = SVAL(inbuf,smb_vwv2);
1368	int deny_mode = SVAL(inbuf,smb_vwv3);
1369	uint32 smb_attr = SVAL(inbuf,smb_vwv5);
1370	/* Breakout the oplock request bits so we can set the
1371		reply bits separately. */
1372	int ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
1373	int core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1374	int oplock_request = ex_oplock_request | core_oplock_request;
1375#if 0
1376	int smb_sattr = SVAL(inbuf,smb_vwv4);
1377	uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
1378#endif
1379	int smb_ofun = SVAL(inbuf,smb_vwv8);
1380	uint32 fattr=0;
1381	int mtime=0;
1382	SMB_STRUCT_STAT sbuf;
1383	int smb_action = 0;
1384	files_struct *fsp;
1385	NTSTATUS status;
1386	SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv9);
1387	ssize_t retval = -1;
1388	uint32 access_mask;
1389	uint32 share_mode;
1390	uint32 create_disposition;
1391	uint32 create_options = 0;
1392
1393	START_PROFILE(SMBopenX);
1394
1395	/* If it's an IPC, pass off the pipe handler. */
1396	if (IS_IPC(conn)) {
1397		if (lp_nt_pipe_support()) {
1398			END_PROFILE(SMBopenX);
1399			return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1400		} else {
1401			END_PROFILE(SMBopenX);
1402			return ERROR_DOS(ERRSRV,ERRaccess);
1403		}
1404	}
1405
1406	/* XXXX we need to handle passed times, sattr and flags */
1407	srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
1408	if (!NT_STATUS_IS_OK(status)) {
1409		END_PROFILE(SMBopenX);
1410		return ERROR_NT(status);
1411	}
1412
1413	status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1414	if (!NT_STATUS_IS_OK(status)) {
1415		END_PROFILE(SMBopenX);
1416		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1417			return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1418		}
1419		return ERROR_NT(status);
1420	}
1421
1422	status = unix_convert(conn, fname, False, NULL, &sbuf);
1423	if (!NT_STATUS_IS_OK(status)) {
1424		END_PROFILE(SMBopenX);
1425		return ERROR_NT(status);
1426	}
1427
1428	status = check_name(conn, fname);
1429	if (!NT_STATUS_IS_OK(status)) {
1430		END_PROFILE(SMBopenX);
1431		return ERROR_NT(status);
1432	}
1433
1434	if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
1435				&access_mask,
1436				&share_mode,
1437				&create_disposition,
1438				&create_options)) {
1439		END_PROFILE(SMBopenX);
1440		return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
1441	}
1442
1443	status = open_file_ntcreate(conn,fname,&sbuf,
1444			access_mask,
1445			share_mode,
1446			create_disposition,
1447			create_options,
1448			smb_attr,
1449			oplock_request,
1450			&smb_action, &fsp);
1451
1452	if (!NT_STATUS_IS_OK(status)) {
1453		END_PROFILE(SMBopenX);
1454		if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1455			/* We have re-scheduled this call. */
1456			return -1;
1457		}
1458		return ERROR_NT(status);
1459	}
1460
1461	/* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
1462	   if the file is truncated or created. */
1463	if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
1464		fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
1465		if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
1466			close_file(fsp,ERROR_CLOSE);
1467			END_PROFILE(SMBopenX);
1468			return ERROR_NT(NT_STATUS_DISK_FULL);
1469		}
1470		retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
1471		if (retval < 0) {
1472			close_file(fsp,ERROR_CLOSE);
1473			END_PROFILE(SMBopenX);
1474			return ERROR_NT(NT_STATUS_DISK_FULL);
1475		}
1476		sbuf.st_size = get_allocation_size(conn,fsp,&sbuf);
1477	}
1478
1479	fattr = dos_mode(conn,fname,&sbuf);
1480	mtime = sbuf.st_mtime;
1481	if (fattr & aDIR) {
1482		close_file(fsp,ERROR_CLOSE);
1483		END_PROFILE(SMBopenX);
1484		return ERROR_DOS(ERRDOS,ERRnoaccess);
1485	}
1486
1487	/* If the caller set the extended oplock request bit
1488		and we granted one (by whatever means) - set the
1489		correct bit for extended oplock reply.
1490	*/
1491
1492	if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1493		smb_action |= EXTENDED_OPLOCK_GRANTED;
1494	}
1495
1496	if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1497		smb_action |= EXTENDED_OPLOCK_GRANTED;
1498	}
1499
1500	/* If the caller set the core oplock request bit
1501		and we granted one (by whatever means) - set the
1502		correct bit for core oplock reply.
1503	*/
1504
1505	if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
1506		SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1507	}
1508
1509	if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1510		SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1511	}
1512
1513	if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1514		set_message(outbuf,19,0,True);
1515	} else {
1516		set_message(outbuf,15,0,True);
1517	}
1518	SSVAL(outbuf,smb_vwv2,fsp->fnum);
1519	SSVAL(outbuf,smb_vwv3,fattr);
1520	if(lp_dos_filetime_resolution(SNUM(conn)) ) {
1521		srv_put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1522	} else {
1523		srv_put_dos_date3(outbuf,smb_vwv4,mtime);
1524	}
1525	SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
1526	SSVAL(outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
1527	SSVAL(outbuf,smb_vwv11,smb_action);
1528
1529	if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
1530		SIVAL(outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
1531	}
1532
1533	END_PROFILE(SMBopenX);
1534	return chain_reply(inbuf,outbuf,length,bufsize);
1535}
1536
1537/****************************************************************************
1538 Reply to a SMBulogoffX.
1539 conn POINTER CAN BE NULL HERE !
1540****************************************************************************/
1541
1542int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1543{
1544	uint16 vuid = SVAL(inbuf,smb_uid);
1545	user_struct *vuser = get_valid_user_struct(vuid);
1546	START_PROFILE(SMBulogoffX);
1547
1548	if(vuser == 0)
1549		DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1550
1551	/* in user level security we are supposed to close any files
1552		open by this user */
1553	if ((vuser != 0) && (lp_security() != SEC_SHARE))
1554		file_close_user(vuid);
1555
1556	invalidate_vuid(vuid);
1557
1558	set_message(outbuf,2,0,True);
1559
1560	DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1561
1562	END_PROFILE(SMBulogoffX);
1563	return chain_reply(inbuf,outbuf,length,bufsize);
1564}
1565
1566/****************************************************************************
1567 Reply to a mknew or a create.
1568****************************************************************************/
1569
1570int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1571{
1572	pstring fname;
1573	int com;
1574	int outsize = 0;
1575	uint32 fattr = SVAL(inbuf,smb_vwv0);
1576	struct timespec ts[2];
1577	files_struct *fsp;
1578	int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1579	SMB_STRUCT_STAT sbuf;
1580	NTSTATUS status;
1581	uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
1582	uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
1583	uint32 create_disposition;
1584	uint32 create_options = 0;
1585
1586	START_PROFILE(SMBcreate);
1587
1588	com = SVAL(inbuf,smb_com);
1589
1590	ts[1] = convert_time_t_to_timespec(srv_make_unix_date3(inbuf + smb_vwv1)); /* mtime. */
1591
1592	srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status);
1593	if (!NT_STATUS_IS_OK(status)) {
1594		END_PROFILE(SMBcreate);
1595		return ERROR_NT(status);
1596	}
1597
1598	status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1599	if (!NT_STATUS_IS_OK(status)) {
1600		END_PROFILE(SMBcreate);
1601		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1602			return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1603		}
1604		return ERROR_NT(status);
1605	}
1606
1607	status = unix_convert(conn, fname, False, NULL, &sbuf);
1608	if (!NT_STATUS_IS_OK(status)) {
1609		END_PROFILE(SMBcreate);
1610		return ERROR_NT(status);
1611	}
1612
1613	status = check_name(conn, fname);
1614	if (!NT_STATUS_IS_OK(status)) {
1615		END_PROFILE(SMBcreate);
1616		return ERROR_NT(status);
1617	}
1618
1619	if (fattr & aVOLID) {
1620		DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1621	}
1622
1623	if(com == SMBmknew) {
1624		/* We should fail if file exists. */
1625		create_disposition = FILE_CREATE;
1626	} else {
1627		/* Create if file doesn't exist, truncate if it does. */
1628		create_disposition = FILE_OVERWRITE_IF;
1629	}
1630
1631	/* Open file using ntcreate. */
1632	status = open_file_ntcreate(conn,fname,&sbuf,
1633				access_mask,
1634				share_mode,
1635				create_disposition,
1636				create_options,
1637				fattr,
1638				oplock_request,
1639				NULL, &fsp);
1640
1641	if (!NT_STATUS_IS_OK(status)) {
1642		END_PROFILE(SMBcreate);
1643		if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1644			/* We have re-scheduled this call. */
1645			return -1;
1646		}
1647		return ERROR_NT(status);
1648	}
1649
1650	ts[0] = get_atimespec(&sbuf); /* atime. */
1651	file_ntimes(conn, fname, ts);
1652
1653	outsize = set_message(outbuf,1,0,True);
1654	SSVAL(outbuf,smb_vwv0,fsp->fnum);
1655
1656	if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1657		SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1658	}
1659
1660	if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1661		SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1662	}
1663
1664	DEBUG( 2, ( "reply_mknew: file %s\n", fname ) );
1665	DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n", fname, fsp->fh->fd, (unsigned int)fattr ) );
1666
1667	END_PROFILE(SMBcreate);
1668	return(outsize);
1669}
1670
1671/****************************************************************************
1672 Reply to a create temporary file.
1673****************************************************************************/
1674
1675int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1676{
1677	pstring fname;
1678	int outsize = 0;
1679	uint32 fattr = SVAL(inbuf,smb_vwv0);
1680	files_struct *fsp;
1681	int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1682	int tmpfd;
1683	SMB_STRUCT_STAT sbuf;
1684	char *p, *s;
1685	NTSTATUS status;
1686	unsigned int namelen;
1687
1688	START_PROFILE(SMBctemp);
1689
1690	srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
1691	if (!NT_STATUS_IS_OK(status)) {
1692		END_PROFILE(SMBctemp);
1693		return ERROR_NT(status);
1694	}
1695	if (*fname) {
1696		pstrcat(fname,"/TMXXXXXX");
1697	} else {
1698		pstrcat(fname,"TMXXXXXX");
1699	}
1700
1701	status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
1702	if (!NT_STATUS_IS_OK(status)) {
1703		END_PROFILE(SMBctemp);
1704		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1705			return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1706		}
1707		return ERROR_NT(status);
1708	}
1709
1710	status = unix_convert(conn, fname, False, NULL, &sbuf);
1711	if (!NT_STATUS_IS_OK(status)) {
1712		END_PROFILE(SMBctemp);
1713		return ERROR_NT(status);
1714	}
1715
1716	status = check_name(conn, fname);
1717	if (!NT_STATUS_IS_OK(status)) {
1718		END_PROFILE(SMBctemp);
1719		return ERROR_NT(status);
1720	}
1721
1722	tmpfd = smb_mkstemp(fname);
1723	if (tmpfd == -1) {
1724		END_PROFILE(SMBctemp);
1725		return(UNIXERROR(ERRDOS,ERRnoaccess));
1726	}
1727
1728	SMB_VFS_STAT(conn,fname,&sbuf);
1729
1730	/* We should fail if file does not exist. */
1731	status = open_file_ntcreate(conn,fname,&sbuf,
1732				FILE_GENERIC_READ | FILE_GENERIC_WRITE,
1733				FILE_SHARE_READ|FILE_SHARE_WRITE,
1734				FILE_OPEN,
1735				0,
1736				fattr,
1737				oplock_request,
1738				NULL, &fsp);
1739
1740	/* close fd from smb_mkstemp() */
1741	close(tmpfd);
1742
1743	if (!NT_STATUS_IS_OK(status)) {
1744		END_PROFILE(SMBctemp);
1745		if (open_was_deferred(SVAL(inbuf,smb_mid))) {
1746			/* We have re-scheduled this call. */
1747			return -1;
1748		}
1749		return ERROR_NT(status);
1750	}
1751
1752	outsize = set_message(outbuf,1,0,True);
1753	SSVAL(outbuf,smb_vwv0,fsp->fnum);
1754
1755	/* the returned filename is relative to the directory */
1756	s = strrchr_m(fname, '/');
1757	if (!s) {
1758		s = fname;
1759	} else {
1760		s++;
1761	}
1762
1763	p = smb_buf(outbuf);
1764#if 0
1765	/* Tested vs W2K3 - this doesn't seem to be here - null terminated filename is the only
1766	   thing in the byte section. JRA */
1767	SSVALS(p, 0, -1); /* what is this? not in spec */
1768#endif
1769	namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
1770	p += namelen;
1771	outsize = set_message_end(outbuf, p);
1772
1773	if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1774		SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1775	}
1776
1777	if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1778		SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1779	}
1780
1781	DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) );
1782	DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname, fsp->fh->fd,
1783			(unsigned int)sbuf.st_mode ) );
1784
1785	END_PROFILE(SMBctemp);
1786	return(outsize);
1787}
1788
1789/*******************************************************************
1790 Check if a user is allowed to rename a file.
1791********************************************************************/
1792
1793static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst, BOOL self_open)
1794{
1795	files_struct *fsp;
1796	uint32 fmode;
1797	NTSTATUS status;
1798
1799	if (!CAN_WRITE(conn)) {
1800		return NT_STATUS_MEDIA_WRITE_PROTECTED;
1801	}
1802
1803	fmode = dos_mode(conn,fname,pst);
1804	if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
1805		return NT_STATUS_NO_SUCH_FILE;
1806	}
1807
1808	if (S_ISDIR(pst->st_mode)) {
1809		return NT_STATUS_OK;
1810	}
1811
1812	status = open_file_ntcreate(conn, fname, pst,
1813				DELETE_ACCESS,
1814				/* If we're checking our fsp don't deny for delete. */
1815				self_open ?
1816					FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE :
1817					FILE_SHARE_READ|FILE_SHARE_WRITE,
1818				FILE_OPEN,
1819				0,
1820				FILE_ATTRIBUTE_NORMAL,
1821				0,
1822				NULL, &fsp);
1823
1824	if (!NT_STATUS_IS_OK(status)) {
1825		return status;
1826	}
1827	close_file(fsp,NORMAL_CLOSE);
1828	return NT_STATUS_OK;
1829}
1830
1831/*******************************************************************
1832 Check if a user is allowed to delete a file.
1833********************************************************************/
1834
1835static NTSTATUS can_delete(connection_struct *conn, char *fname,
1836			   uint32 dirtype, BOOL can_defer)
1837{
1838	SMB_STRUCT_STAT sbuf;
1839	uint32 fattr;
1840	files_struct *fsp;
1841	uint32 dirtype_orig = dirtype;
1842	NTSTATUS status;
1843
1844	DEBUG(10,("can_delete: %s, dirtype = %d\n", fname, dirtype ));
1845
1846	if (!CAN_WRITE(conn)) {
1847		return NT_STATUS_MEDIA_WRITE_PROTECTED;
1848	}
1849
1850	if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
1851		return map_nt_error_from_unix(errno);
1852	}
1853
1854	fattr = dos_mode(conn,fname,&sbuf);
1855
1856	if (dirtype & FILE_ATTRIBUTE_NORMAL) {
1857		dirtype = aDIR|aARCH|aRONLY;
1858	}
1859
1860	dirtype &= (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM);
1861	if (!dirtype) {
1862		return NT_STATUS_NO_SUCH_FILE;
1863	}
1864
1865	if (!dir_check_ftype(conn, fattr, dirtype)) {
1866		if (fattr & aDIR) {
1867			return NT_STATUS_FILE_IS_A_DIRECTORY;
1868		}
1869		return NT_STATUS_NO_SUCH_FILE;
1870	}
1871
1872	if (dirtype_orig & 0x8000) {
1873		/* These will never be set for POSIX. */
1874		return NT_STATUS_NO_SUCH_FILE;
1875	}
1876
1877#if 0
1878	if ((fattr & dirtype) & FILE_ATTRIBUTE_DIRECTORY) {
1879                return NT_STATUS_FILE_IS_A_DIRECTORY;
1880        }
1881
1882        if ((fattr & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)) {
1883                return NT_STATUS_NO_SUCH_FILE;
1884        }
1885
1886	if (dirtype & 0xFF00) {
1887		/* These will never be set for POSIX. */
1888		return NT_STATUS_NO_SUCH_FILE;
1889	}
1890
1891	dirtype &= 0xFF;
1892	if (!dirtype) {
1893		return NT_STATUS_NO_SUCH_FILE;
1894	}
1895
1896	/* Can't delete a directory. */
1897	if (fattr & aDIR) {
1898		return NT_STATUS_FILE_IS_A_DIRECTORY;
1899	}
1900#endif
1901
1902#if 0 /* JRATEST */
1903	else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1904		return NT_STATUS_OBJECT_NAME_INVALID;
1905#endif /* JRATEST */
1906
1907	/* Fix for bug #3035 from SATOH Fumiyasu <fumiyas@miraclelinux.com>
1908
1909	  On a Windows share, a file with read-only dosmode can be opened with
1910	  DELETE_ACCESS. But on a Samba share (delete readonly = no), it
1911	  fails with NT_STATUS_CANNOT_DELETE error.
1912
1913	  This semantic causes a problem that a user can not
1914	  rename a file with read-only dosmode on a Samba share
1915	  from a Windows command prompt (i.e. cmd.exe, but can rename
1916	  from Windows Explorer).
1917	*/
1918
1919	if (!lp_delete_readonly(SNUM(conn))) {
1920		if (fattr & aRONLY) {
1921			return NT_STATUS_CANNOT_DELETE;
1922		}
1923	}
1924
1925	/* On open checks the open itself will check the share mode, so
1926	   don't do it here as we'll get it wrong. */
1927
1928	status = open_file_ntcreate(conn, fname, &sbuf,
1929				    DELETE_ACCESS,
1930				    FILE_SHARE_NONE,
1931				    FILE_OPEN,
1932				    0,
1933				    FILE_ATTRIBUTE_NORMAL,
1934				    can_defer ? 0 : INTERNAL_OPEN_ONLY,
1935				    NULL, &fsp);
1936
1937	if (NT_STATUS_IS_OK(status)) {
1938		close_file(fsp,NORMAL_CLOSE);
1939	}
1940	return status;
1941}
1942
1943/****************************************************************************
1944 The guts of the unlink command, split out so it may be called by the NT SMB
1945 code.
1946****************************************************************************/
1947
1948NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype,
1949			  char *name, BOOL has_wild, BOOL can_defer)
1950{
1951	pstring directory;
1952	pstring mask;
1953	char *p;
1954	int count=0;
1955	NTSTATUS status = NT_STATUS_OK;
1956	SMB_STRUCT_STAT sbuf;
1957
1958	*directory = *mask = 0;
1959
1960	status = unix_convert(conn, name, has_wild, NULL, &sbuf);
1961	if (!NT_STATUS_IS_OK(status)) {
1962		return status;
1963	}
1964
1965	p = strrchr_m(name,'/');
1966	if (!p) {
1967		pstrcpy(directory,".");
1968		pstrcpy(mask,name);
1969	} else {
1970		*p = 0;
1971		pstrcpy(directory,name);
1972		pstrcpy(mask,p+1);
1973	}
1974
1975	/*
1976	 * We should only check the mangled cache
1977	 * here if unix_convert failed. This means
1978	 * that the path in 'mask' doesn't exist
1979	 * on the file system and so we need to look
1980	 * for a possible mangle. This patch from
1981	 * Tine Smukavec <valentin.smukavec@hermes.si>.
1982	 */
1983
1984	if (!VALID_STAT(sbuf) && mangle_is_mangled(mask,conn->params))
1985		mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
1986
1987	if (!has_wild) {
1988		pstrcat(directory,"/");
1989		pstrcat(directory,mask);
1990		if (dirtype == 0) {
1991			dirtype = FILE_ATTRIBUTE_NORMAL;
1992		}
1993
1994		status = check_name(conn, directory);
1995		if (!NT_STATUS_IS_OK(status)) {
1996			return status;
1997		}
1998
1999		status = can_delete(conn,directory,dirtype,can_defer);
2000		if (!NT_STATUS_IS_OK(status)) {
2001			return status;
2002		}
2003
2004		if (SMB_VFS_UNLINK(conn,directory) == 0) {
2005			count++;
2006			notify_fname(conn, NOTIFY_ACTION_REMOVED,
2007				     FILE_NOTIFY_CHANGE_FILE_NAME,
2008				     directory);
2009		}
2010	} else {
2011		struct smb_Dir *dir_hnd = NULL;
2012		long offset = 0;
2013		const char *dname;
2014
2015		if ((dirtype & SAMBA_ATTRIBUTES_MASK) == aDIR) {
2016			return NT_STATUS_OBJECT_NAME_INVALID;
2017		}
2018
2019		if (strequal(mask,"????????.???")) {
2020			pstrcpy(mask,"*");
2021		}
2022
2023		status = check_name(conn, directory);
2024		if (!NT_STATUS_IS_OK(status)) {
2025			return status;
2026		}
2027
2028		dir_hnd = OpenDir(conn, directory, mask, dirtype);
2029		if (dir_hnd == NULL) {
2030			return map_nt_error_from_unix(errno);
2031		}
2032
2033		/* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
2034		   the pattern matches against the long name, otherwise the short name
2035		   We don't implement this yet XXXX
2036		*/
2037
2038		status = NT_STATUS_NO_SUCH_FILE;
2039
2040		while ((dname = ReadDirName(dir_hnd, &offset))) {
2041			SMB_STRUCT_STAT st;
2042			pstring fname;
2043			pstrcpy(fname,dname);
2044
2045			if (!is_visible_file(conn, directory, dname, &st, True)) {
2046				continue;
2047			}
2048
2049			/* Quick check for "." and ".." */
2050			if (fname[0] == '.') {
2051				if (!fname[1] || (fname[1] == '.' && !fname[2])) {
2052					continue;
2053				}
2054			}
2055
2056			if(!mask_match(fname, mask, conn->case_sensitive)) {
2057				continue;
2058			}
2059
2060			slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
2061
2062			status = check_name(conn, fname);
2063			if (!NT_STATUS_IS_OK(status)) {
2064				CloseDir(dir_hnd);
2065				return status;
2066			}
2067
2068			status = can_delete(conn, fname, dirtype, can_defer);
2069			if (!NT_STATUS_IS_OK(status)) {
2070				continue;
2071			}
2072			if (SMB_VFS_UNLINK(conn,fname) == 0) {
2073				count++;
2074				DEBUG(3,("unlink_internals: succesful unlink "
2075					 "[%s]\n",fname));
2076				notify_fname(conn, NOTIFY_ACTION_REMOVED,
2077					     FILE_NOTIFY_CHANGE_FILE_NAME,
2078					     fname);
2079			}
2080
2081		}
2082		CloseDir(dir_hnd);
2083	}
2084
2085	if (count == 0 && NT_STATUS_IS_OK(status)) {
2086		status = map_nt_error_from_unix(errno);
2087	}
2088
2089	return status;
2090}
2091
2092/****************************************************************************
2093 Reply to a unlink
2094****************************************************************************/
2095
2096int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
2097		 int dum_buffsize)
2098{
2099	int outsize = 0;
2100	pstring name;
2101	uint32 dirtype;
2102	NTSTATUS status;
2103	BOOL path_contains_wcard = False;
2104
2105	START_PROFILE(SMBunlink);
2106
2107	dirtype = SVAL(inbuf,smb_vwv0);
2108
2109	srvstr_get_path_wcard(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard);
2110	if (!NT_STATUS_IS_OK(status)) {
2111		END_PROFILE(SMBunlink);
2112		return ERROR_NT(status);
2113	}
2114
2115	status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &path_contains_wcard);
2116	if (!NT_STATUS_IS_OK(status)) {
2117		END_PROFILE(SMBunlink);
2118		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
2119			return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
2120		}
2121		return ERROR_NT(status);
2122	}
2123
2124	DEBUG(3,("reply_unlink : %s\n",name));
2125
2126	status = unlink_internals(conn, dirtype, name, path_contains_wcard,
2127				  True);
2128	if (!NT_STATUS_IS_OK(status)) {
2129		if (open_was_deferred(SVAL(inbuf,smb_mid))) {
2130			/* We have re-scheduled this call. */
2131			return -1;
2132		}
2133		return ERROR_NT(status);
2134	}
2135
2136	outsize = set_message(outbuf,0,0,False);
2137
2138	END_PROFILE(SMBunlink);
2139	return outsize;
2140}
2141
2142/****************************************************************************
2143 Fail for readbraw.
2144****************************************************************************/
2145
2146static void fail_readraw(void)
2147{
2148	pstring errstr;
2149	slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
2150		strerror(errno) );
2151	exit_server_cleanly(errstr);
2152}
2153
2154#if defined(WITH_SENDFILE)
2155/****************************************************************************
2156 Fake (read/write) sendfile. Returns -1 on read or write fail.
2157****************************************************************************/
2158
2159static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, int bufsize)
2160{
2161	ssize_t ret=0;
2162
2163	/* Paranioa check... */
2164	if (nread > bufsize) {
2165		fail_readraw();
2166	}
2167
2168	if (nread > 0) {
2169		ret = read_file(fsp,buf,startpos,nread);
2170		if (ret == -1) {
2171			return -1;
2172		}
2173	}
2174
2175	/* If we had a short read, fill with zeros. */
2176	if (ret < nread) {
2177		memset(buf, '\0', nread - ret);
2178	}
2179
2180	if (write_data(smbd_server_fd(),buf,nread) != nread) {
2181		return -1;
2182	}
2183
2184	return (ssize_t)nread;
2185}
2186#endif
2187
2188/****************************************************************************
2189 Use sendfile in readbraw.
2190****************************************************************************/
2191
2192void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
2193		ssize_t mincount, char *outbuf, int out_buffsize)
2194{
2195	ssize_t ret=0;
2196
2197#if defined(WITH_SENDFILE)
2198	/*
2199	 * We can only use sendfile on a non-chained packet
2200	 * but we can use on a non-oplocked file. tridge proved this
2201	 * on a train in Germany :-). JRA.
2202	 * reply_readbraw has already checked the length.
2203	 */
2204
2205	if ( (chain_size == 0) && (nread > 0) &&
2206	    (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
2207		DATA_BLOB header;
2208
2209		_smb_setlen(outbuf,nread);
2210		header.data = (uint8 *)outbuf;
2211		header.length = 4;
2212		header.free = NULL;
2213
2214		if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, nread) == -1) {
2215			/* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2216			if (errno == ENOSYS) {
2217				goto normal_readbraw;
2218			}
2219
2220			/*
2221			 * Special hack for broken Linux with no working sendfile. If we
2222			 * return EINTR we sent the header but not the rest of the data.
2223			 * Fake this up by doing read/write calls.
2224			 */
2225			if (errno == EINTR) {
2226				/* Ensure we don't do this again. */
2227				set_use_sendfile(SNUM(conn), False);
2228				DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
2229
2230				if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
2231					DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
2232						fsp->fsp_name, strerror(errno) ));
2233					exit_server_cleanly("send_file_readbraw fake_sendfile failed");
2234				}
2235				return;
2236			}
2237
2238			DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
2239				fsp->fsp_name, strerror(errno) ));
2240			exit_server_cleanly("send_file_readbraw sendfile failed");
2241		}
2242
2243		return;
2244	}
2245
2246  normal_readbraw:
2247
2248#endif
2249
2250	if (nread > 0) {
2251		ret = read_file(fsp,outbuf+4,startpos,nread);
2252#if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2253		if (ret < mincount)
2254			ret = 0;
2255#else
2256		if (ret < nread)
2257			ret = 0;
2258#endif
2259	}
2260
2261	_smb_setlen(outbuf,ret);
2262	if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
2263		fail_readraw();
2264}
2265
2266/****************************************************************************
2267 Reply to a readbraw (core+ protocol).
2268****************************************************************************/
2269
2270int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
2271{
2272	ssize_t maxcount,mincount;
2273	size_t nread = 0;
2274	SMB_OFF_T startpos;
2275	char *header = outbuf;
2276	files_struct *fsp;
2277	START_PROFILE(SMBreadbraw);
2278
2279	if (srv_is_signing_active()) {
2280		exit_server_cleanly("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
2281	}
2282
2283	/*
2284	 * Special check if an oplock break has been issued
2285	 * and the readraw request croses on the wire, we must
2286	 * return a zero length response here.
2287	 */
2288
2289	fsp = file_fsp(inbuf,smb_vwv0);
2290
2291	if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
2292		/*
2293		 * fsp could be NULL here so use the value from the packet. JRA.
2294		 */
2295		DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
2296		_smb_setlen(header,0);
2297		if (write_data(smbd_server_fd(),header,4) != 4)
2298			fail_readraw();
2299		END_PROFILE(SMBreadbraw);
2300		return(-1);
2301	}
2302
2303	CHECK_FSP(fsp,conn);
2304
2305	flush_write_cache(fsp, READRAW_FLUSH);
2306
2307	startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
2308	if(CVAL(inbuf,smb_wct) == 10) {
2309		/*
2310		 * This is a large offset (64 bit) read.
2311		 */
2312#ifdef LARGE_SMB_OFF_T
2313
2314		startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
2315
2316#else /* !LARGE_SMB_OFF_T */
2317
2318		/*
2319		 * Ensure we haven't been sent a >32 bit offset.
2320		 */
2321
2322		if(IVAL(inbuf,smb_vwv8) != 0) {
2323			DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
232464 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
2325			_smb_setlen(header,0);
2326			if (write_data(smbd_server_fd(),header,4) != 4)
2327				fail_readraw();
2328			END_PROFILE(SMBreadbraw);
2329			return(-1);
2330		}
2331
2332#endif /* LARGE_SMB_OFF_T */
2333
2334		if(startpos < 0) {
2335			DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
2336			_smb_setlen(header,0);
2337			if (write_data(smbd_server_fd(),header,4) != 4)
2338				fail_readraw();
2339			END_PROFILE(SMBreadbraw);
2340			return(-1);
2341		}
2342	}
2343	maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
2344	mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
2345
2346	/* ensure we don't overrun the packet size */
2347	maxcount = MIN(65535,maxcount);
2348
2349	if (!is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2350		SMB_STRUCT_STAT st;
2351		SMB_OFF_T size = 0;
2352
2353		if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) {
2354			size = st.st_size;
2355		}
2356
2357		if (startpos >= size) {
2358			nread = 0;
2359		} else {
2360			nread = MIN(maxcount,(size - startpos));
2361		}
2362	}
2363
2364#if 0 /* mincount appears to be ignored in a W2K server. JRA. */
2365	if (nread < mincount)
2366		nread = 0;
2367#endif
2368
2369	DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%lu min=%lu nread=%lu\n", fsp->fnum, (double)startpos,
2370				(unsigned long)maxcount, (unsigned long)mincount, (unsigned long)nread ) );
2371
2372	send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
2373
2374	DEBUG(5,("readbraw finished\n"));
2375	END_PROFILE(SMBreadbraw);
2376	return -1;
2377}
2378
2379#undef DBGC_CLASS
2380#define DBGC_CLASS DBGC_LOCKING
2381
2382/****************************************************************************
2383 Reply to a lockread (core+ protocol).
2384****************************************************************************/
2385
2386int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
2387{
2388	ssize_t nread = -1;
2389	char *data;
2390	int outsize = 0;
2391	SMB_OFF_T startpos;
2392	size_t numtoread;
2393	NTSTATUS status;
2394	files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2395	struct byte_range_lock *br_lck = NULL;
2396	START_PROFILE(SMBlockread);
2397
2398	CHECK_FSP(fsp,conn);
2399	if (!CHECK_READ(fsp,inbuf)) {
2400		return(ERROR_DOS(ERRDOS,ERRbadaccess));
2401	}
2402
2403	release_level_2_oplocks_on_change(fsp);
2404
2405	numtoread = SVAL(inbuf,smb_vwv1);
2406	startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2407
2408	outsize = set_message(outbuf,5,3,True);
2409	numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2410	data = smb_buf(outbuf) + 3;
2411
2412	/*
2413	 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
2414	 * protocol request that predates the read/write lock concept.
2415	 * Thus instead of asking for a read lock here we need to ask
2416	 * for a write lock. JRA.
2417	 * Note that the requested lock size is unaffected by max_recv.
2418	 */
2419
2420	br_lck = do_lock(fsp,
2421			(uint32)SVAL(inbuf,smb_pid),
2422			(SMB_BIG_UINT)numtoread,
2423			(SMB_BIG_UINT)startpos,
2424			WRITE_LOCK,
2425			WINDOWS_LOCK,
2426			False, /* Non-blocking lock. */
2427			&status,
2428			NULL);
2429	TALLOC_FREE(br_lck);
2430
2431	if (NT_STATUS_V(status)) {
2432		END_PROFILE(SMBlockread);
2433		return ERROR_NT(status);
2434	}
2435
2436	/*
2437	 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
2438	 */
2439
2440	if (numtoread > max_recv) {
2441		DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
2442Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2443			(unsigned int)numtoread, (unsigned int)max_recv ));
2444		numtoread = MIN(numtoread,max_recv);
2445	}
2446	nread = read_file(fsp,data,startpos,numtoread);
2447
2448	if (nread < 0) {
2449		END_PROFILE(SMBlockread);
2450		return(UNIXERROR(ERRDOS,ERRnoaccess));
2451	}
2452
2453	outsize += nread;
2454	SSVAL(outbuf,smb_vwv0,nread);
2455	SSVAL(outbuf,smb_vwv5,nread+3);
2456	SSVAL(smb_buf(outbuf),1,nread);
2457
2458	DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
2459		 fsp->fnum, (int)numtoread, (int)nread));
2460
2461	END_PROFILE(SMBlockread);
2462	return(outsize);
2463}
2464
2465#undef DBGC_CLASS
2466#define DBGC_CLASS DBGC_ALL
2467
2468/****************************************************************************
2469 Reply to a read.
2470****************************************************************************/
2471
2472int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2473{
2474	size_t numtoread;
2475	ssize_t nread = 0;
2476	char *data;
2477	SMB_OFF_T startpos;
2478	int outsize = 0;
2479	files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2480	START_PROFILE(SMBread);
2481
2482	CHECK_FSP(fsp,conn);
2483	if (!CHECK_READ(fsp,inbuf)) {
2484		return(ERROR_DOS(ERRDOS,ERRbadaccess));
2485	}
2486
2487	numtoread = SVAL(inbuf,smb_vwv1);
2488	startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2489
2490	outsize = set_message(outbuf,5,3,True);
2491	numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
2492	/*
2493	 * The requested read size cannot be greater than max_recv. JRA.
2494	 */
2495	if (numtoread > max_recv) {
2496		DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
2497Returning short read of maximum allowed for compatibility with Windows 2000.\n",
2498			(unsigned int)numtoread, (unsigned int)max_recv ));
2499		numtoread = MIN(numtoread,max_recv);
2500	}
2501
2502	data = smb_buf(outbuf) + 3;
2503
2504	if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2505		END_PROFILE(SMBread);
2506		return ERROR_DOS(ERRDOS,ERRlock);
2507	}
2508
2509	if (numtoread > 0)
2510		nread = read_file(fsp,data,startpos,numtoread);
2511
2512	if (nread < 0) {
2513		END_PROFILE(SMBread);
2514		return(UNIXERROR(ERRDOS,ERRnoaccess));
2515	}
2516
2517	outsize += nread;
2518	SSVAL(outbuf,smb_vwv0,nread);
2519	SSVAL(outbuf,smb_vwv5,nread+3);
2520	SCVAL(smb_buf(outbuf),0,1);
2521	SSVAL(smb_buf(outbuf),1,nread);
2522
2523	DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
2524		fsp->fnum, (int)numtoread, (int)nread ) );
2525
2526	END_PROFILE(SMBread);
2527	return(outsize);
2528}
2529
2530/****************************************************************************
2531 Reply to a read and X - possibly using sendfile.
2532****************************************************************************/
2533
2534int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
2535		files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
2536{
2537	int outsize = 0;
2538	ssize_t nread = -1;
2539	char *data = smb_buf(outbuf);
2540
2541#if defined(WITH_SENDFILE)
2542	/*
2543	 * We can only use sendfile on a non-chained packet
2544	 * but we can use on a non-oplocked file. tridge proved this
2545	 * on a train in Germany :-). JRA.
2546	 */
2547
2548	if ((chain_size == 0) && (CVAL(inbuf,smb_vwv0) == 0xFF) &&
2549	    lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
2550		SMB_STRUCT_STAT sbuf;
2551		DATA_BLOB header;
2552
2553		if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1)
2554			return(UNIXERROR(ERRDOS,ERRnoaccess));
2555
2556		if (startpos > sbuf.st_size)
2557			goto normal_read;
2558
2559		if (smb_maxcnt > (sbuf.st_size - startpos))
2560			smb_maxcnt = (sbuf.st_size - startpos);
2561
2562		if (smb_maxcnt == 0)
2563			goto normal_read;
2564
2565		/*
2566		 * Set up the packet header before send. We
2567		 * assume here the sendfile will work (get the
2568		 * correct amount of data).
2569		 */
2570
2571		SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2572		SSVAL(outbuf,smb_vwv5,smb_maxcnt);
2573		SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2574		SSVAL(outbuf,smb_vwv7,((smb_maxcnt >> 16) & 1));
2575		SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
2576		SCVAL(outbuf,smb_vwv0,0xFF);
2577		set_message(outbuf,12,smb_maxcnt,False);
2578		header.data = (uint8 *)outbuf;
2579		header.length = data - outbuf;
2580		header.free = NULL;
2581
2582		if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
2583			/* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
2584			if (errno == ENOSYS) {
2585				goto normal_read;
2586			}
2587
2588			/*
2589			 * Special hack for broken Linux with no working sendfile. If we
2590			 * return EINTR we sent the header but not the rest of the data.
2591			 * Fake this up by doing read/write calls.
2592			 */
2593
2594			if (errno == EINTR) {
2595				/* Ensure we don't do this again. */
2596				set_use_sendfile(SNUM(conn), False);
2597				DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
2598
2599				if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
2600							len_outbuf - (data-outbuf))) == -1) {
2601					DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
2602						fsp->fsp_name, strerror(errno) ));
2603					exit_server_cleanly("send_file_readX: fake_sendfile failed");
2604				}
2605				DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
2606					fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2607				/* Returning -1 here means successful sendfile. */
2608				return -1;
2609			}
2610
2611			DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
2612				fsp->fsp_name, strerror(errno) ));
2613			exit_server_cleanly("send_file_readX sendfile failed");
2614		}
2615
2616		DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
2617			fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2618		/* Returning -1 here means successful sendfile. */
2619		return -1;
2620	}
2621
2622  normal_read:
2623
2624#endif
2625
2626	nread = read_file(fsp,data,startpos,smb_maxcnt);
2627
2628	if (nread < 0) {
2629		return(UNIXERROR(ERRDOS,ERRnoaccess));
2630	}
2631
2632	outsize = set_message(outbuf,12,nread,False);
2633	SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
2634	SSVAL(outbuf,smb_vwv5,nread);
2635	SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
2636	SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1));
2637	SSVAL(smb_buf(outbuf),-2,nread);
2638
2639	DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
2640		fsp->fnum, (int)smb_maxcnt, (int)nread ) );
2641
2642	/* Returning the number of bytes we want to send back - including header. */
2643	return outsize;
2644}
2645
2646/****************************************************************************
2647 Reply to a read and X.
2648****************************************************************************/
2649
2650int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2651{
2652	files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2653	SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2654	ssize_t nread = -1;
2655	size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
2656#if 0
2657	size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
2658#endif
2659
2660	START_PROFILE(SMBreadX);
2661
2662	/* If it's an IPC, pass off the pipe handler. */
2663	if (IS_IPC(conn)) {
2664		END_PROFILE(SMBreadX);
2665		return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
2666	}
2667
2668	CHECK_FSP(fsp,conn);
2669	if (!CHECK_READ(fsp,inbuf)) {
2670		return(ERROR_DOS(ERRDOS,ERRbadaccess));
2671	}
2672
2673	set_message(outbuf,12,0,True);
2674
2675	if (global_client_caps & CAP_LARGE_READX) {
2676		if (SVAL(inbuf,smb_vwv7) == 1) {
2677			smb_maxcnt |= (1<<16);
2678		}
2679		if (smb_maxcnt > BUFFER_SIZE) {
2680			DEBUG(0,("reply_read_and_X - read too large (%u) for reply buffer %u\n",
2681				(unsigned int)smb_maxcnt, (unsigned int)BUFFER_SIZE));
2682			END_PROFILE(SMBreadX);
2683			return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2684		}
2685	}
2686
2687	if(CVAL(inbuf,smb_wct) == 12) {
2688#ifdef LARGE_SMB_OFF_T
2689		/*
2690		 * This is a large offset (64 bit) read.
2691		 */
2692		startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
2693
2694#else /* !LARGE_SMB_OFF_T */
2695
2696		/*
2697		 * Ensure we haven't been sent a >32 bit offset.
2698		 */
2699
2700		if(IVAL(inbuf,smb_vwv10) != 0) {
2701			DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
270264 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
2703			END_PROFILE(SMBreadX);
2704			return ERROR_DOS(ERRDOS,ERRbadaccess);
2705		}
2706
2707#endif /* LARGE_SMB_OFF_T */
2708
2709	}
2710
2711	if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
2712		END_PROFILE(SMBreadX);
2713		return ERROR_DOS(ERRDOS,ERRlock);
2714	}
2715
2716	if (schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) {
2717		END_PROFILE(SMBreadX);
2718		return -1;
2719	}
2720
2721	nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
2722	/* Only call chain_reply if not an error. */
2723	if (nread != -1 && SVAL(outbuf,smb_rcls) == 0) {
2724		nread = chain_reply(inbuf,outbuf,length,bufsize);
2725	}
2726
2727	END_PROFILE(SMBreadX);
2728	return nread;
2729}
2730
2731/****************************************************************************
2732 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2733****************************************************************************/
2734
2735int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2736{
2737	ssize_t nwritten=0;
2738	ssize_t total_written=0;
2739	size_t numtowrite=0;
2740	size_t tcount;
2741	SMB_OFF_T startpos;
2742	char *data=NULL;
2743	BOOL write_through;
2744	files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2745	int outsize = 0;
2746	NTSTATUS status;
2747	START_PROFILE(SMBwritebraw);
2748
2749	if (srv_is_signing_active()) {
2750		exit_server_cleanly("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2751	}
2752
2753	CHECK_FSP(fsp,conn);
2754	if (!CHECK_WRITE(fsp)) {
2755		return(ERROR_DOS(ERRDOS,ERRbadaccess));
2756	}
2757
2758	tcount = IVAL(inbuf,smb_vwv1);
2759	startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2760	write_through = BITSETW(inbuf+smb_vwv7,0);
2761
2762	/* We have to deal with slightly different formats depending
2763		on whether we are using the core+ or lanman1.0 protocol */
2764
2765	if(Protocol <= PROTOCOL_COREPLUS) {
2766		numtowrite = SVAL(smb_buf(inbuf),-2);
2767		data = smb_buf(inbuf);
2768	} else {
2769		numtowrite = SVAL(inbuf,smb_vwv10);
2770		data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2771	}
2772
2773	/* force the error type */
2774	SCVAL(inbuf,smb_com,SMBwritec);
2775	SCVAL(outbuf,smb_com,SMBwritec);
2776
2777	if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2778		END_PROFILE(SMBwritebraw);
2779		return(ERROR_DOS(ERRDOS,ERRlock));
2780	}
2781
2782	if (numtowrite>0)
2783		nwritten = write_file(fsp,data,startpos,numtowrite);
2784
2785	DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2786		fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2787
2788	if (nwritten < (ssize_t)numtowrite)  {
2789		END_PROFILE(SMBwritebraw);
2790		return(UNIXERROR(ERRHRD,ERRdiskfull));
2791	}
2792
2793	total_written = nwritten;
2794
2795	/* Return a message to the redirector to tell it to send more bytes */
2796	SCVAL(outbuf,smb_com,SMBwritebraw);
2797	SSVALS(outbuf,smb_vwv0,-1);
2798	outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2799	show_msg(outbuf);
2800	if (!send_smb(smbd_server_fd(),outbuf))
2801		exit_server_cleanly("reply_writebraw: send_smb failed.");
2802
2803	/* Now read the raw data into the buffer and write it */
2804	if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2805		exit_server_cleanly("secondary writebraw failed");
2806	}
2807
2808	/* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2809	numtowrite = smb_len(inbuf);
2810
2811	/* Set up outbuf to return the correct return */
2812	outsize = set_message(outbuf,1,0,True);
2813	SCVAL(outbuf,smb_com,SMBwritec);
2814
2815	if (numtowrite != 0) {
2816
2817		if (numtowrite > BUFFER_SIZE) {
2818			DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2819				(unsigned int)numtowrite ));
2820			exit_server_cleanly("secondary writebraw failed");
2821		}
2822
2823		if (tcount > nwritten+numtowrite) {
2824			DEBUG(3,("Client overestimated the write %d %d %d\n",
2825				(int)tcount,(int)nwritten,(int)numtowrite));
2826		}
2827
2828		if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2829			DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2830				strerror(errno) ));
2831			exit_server_cleanly("secondary writebraw failed");
2832		}
2833
2834		nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2835		if (nwritten == -1) {
2836			END_PROFILE(SMBwritebraw);
2837			return(UNIXERROR(ERRHRD,ERRdiskfull));
2838		}
2839
2840		if (nwritten < (ssize_t)numtowrite) {
2841			SCVAL(outbuf,smb_rcls,ERRHRD);
2842			SSVAL(outbuf,smb_err,ERRdiskfull);
2843		}
2844
2845		if (nwritten > 0)
2846			total_written += nwritten;
2847 	}
2848
2849	SSVAL(outbuf,smb_vwv0,total_written);
2850
2851	status = sync_file(conn, fsp, write_through);
2852	if (!NT_STATUS_IS_OK(status)) {
2853		DEBUG(5,("reply_writebraw: sync_file for %s returned %s\n",
2854			fsp->fsp_name, nt_errstr(status) ));
2855		END_PROFILE(SMBwritebraw);
2856		return ERROR_NT(status);
2857	}
2858
2859	DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2860		fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2861
2862	/* we won't return a status if write through is not selected - this follows what WfWg does */
2863	END_PROFILE(SMBwritebraw);
2864	if (!write_through && total_written==tcount) {
2865
2866#if RABBIT_PELLET_FIX
2867		/*
2868		 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2869		 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2870		 */
2871		if (!send_keepalive(smbd_server_fd()))
2872			exit_server_cleanly("reply_writebraw: send of keepalive failed");
2873#endif
2874		return(-1);
2875	}
2876
2877	return(outsize);
2878}
2879
2880#undef DBGC_CLASS
2881#define DBGC_CLASS DBGC_LOCKING
2882
2883/****************************************************************************
2884 Reply to a writeunlock (core+).
2885****************************************************************************/
2886
2887int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2888		      int size, int dum_buffsize)
2889{
2890	ssize_t nwritten = -1;
2891	size_t numtowrite;
2892	SMB_OFF_T startpos;
2893	char *data;
2894	NTSTATUS status = NT_STATUS_OK;
2895	files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2896	int outsize = 0;
2897	START_PROFILE(SMBwriteunlock);
2898
2899	CHECK_FSP(fsp,conn);
2900	if (!CHECK_WRITE(fsp)) {
2901		return(ERROR_DOS(ERRDOS,ERRbadaccess));
2902	}
2903
2904	numtowrite = SVAL(inbuf,smb_vwv1);
2905	startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2906	data = smb_buf(inbuf) + 3;
2907
2908	if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2909		END_PROFILE(SMBwriteunlock);
2910		return ERROR_DOS(ERRDOS,ERRlock);
2911	}
2912
2913	/* The special X/Open SMB protocol handling of
2914	   zero length writes is *NOT* done for
2915	   this call */
2916	if(numtowrite == 0) {
2917		nwritten = 0;
2918	} else {
2919		nwritten = write_file(fsp,data,startpos,numtowrite);
2920	}
2921
2922	status = sync_file(conn, fsp, False /* write through */);
2923	if (!NT_STATUS_IS_OK(status)) {
2924		END_PROFILE(SMBwriteunlock);
2925		DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
2926			fsp->fsp_name, nt_errstr(status) ));
2927		return ERROR_NT(status);
2928	}
2929
2930	if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2931		END_PROFILE(SMBwriteunlock);
2932		return(UNIXERROR(ERRHRD,ERRdiskfull));
2933	}
2934
2935	if (numtowrite) {
2936		status = do_unlock(fsp,
2937				(uint32)SVAL(inbuf,smb_pid),
2938				(SMB_BIG_UINT)numtowrite,
2939				(SMB_BIG_UINT)startpos,
2940				WINDOWS_LOCK);
2941
2942		if (NT_STATUS_V(status)) {
2943			END_PROFILE(SMBwriteunlock);
2944			return ERROR_NT(status);
2945		}
2946	}
2947
2948	outsize = set_message(outbuf,1,0,True);
2949
2950	SSVAL(outbuf,smb_vwv0,nwritten);
2951
2952	DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2953		 fsp->fnum, (int)numtowrite, (int)nwritten));
2954
2955	END_PROFILE(SMBwriteunlock);
2956	return outsize;
2957}
2958
2959#undef DBGC_CLASS
2960#define DBGC_CLASS DBGC_ALL
2961
2962/****************************************************************************
2963 Reply to a write.
2964****************************************************************************/
2965
2966int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2967{
2968	size_t numtowrite;
2969	ssize_t nwritten = -1;
2970	SMB_OFF_T startpos;
2971	char *data;
2972	files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2973	int outsize = 0;
2974	NTSTATUS status;
2975	START_PROFILE(SMBwrite);
2976
2977	/* If it's an IPC, pass off the pipe handler. */
2978	if (IS_IPC(conn)) {
2979		END_PROFILE(SMBwrite);
2980		return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2981	}
2982
2983	CHECK_FSP(fsp,conn);
2984	if (!CHECK_WRITE(fsp)) {
2985		END_PROFILE(SMBwrite);
2986		return(ERROR_DOS(ERRDOS,ERRbadaccess));
2987	}
2988
2989	numtowrite = SVAL(inbuf,smb_vwv1);
2990	startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2991	data = smb_buf(inbuf) + 3;
2992
2993	if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
2994		END_PROFILE(SMBwrite);
2995		return ERROR_DOS(ERRDOS,ERRlock);
2996	}
2997
2998	/*
2999	 * X/Open SMB protocol says that if smb_vwv1 is
3000	 * zero then the file size should be extended or
3001	 * truncated to the size given in smb_vwv[2-3].
3002	 */
3003
3004	if(numtowrite == 0) {
3005		/*
3006		 * This is actually an allocate call, and set EOF. JRA.
3007		 */
3008		nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
3009		if (nwritten < 0) {
3010			END_PROFILE(SMBwrite);
3011			return ERROR_NT(NT_STATUS_DISK_FULL);
3012		}
3013		nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
3014		if (nwritten < 0) {
3015			END_PROFILE(SMBwrite);
3016			return ERROR_NT(NT_STATUS_DISK_FULL);
3017		}
3018	} else
3019		nwritten = write_file(fsp,data,startpos,numtowrite);
3020
3021	status = sync_file(conn, fsp, False);
3022	if (!NT_STATUS_IS_OK(status)) {
3023		END_PROFILE(SMBwrite);
3024		DEBUG(5,("reply_write: sync_file for %s returned %s\n",
3025			fsp->fsp_name, nt_errstr(status) ));
3026		return ERROR_NT(status);
3027	}
3028
3029	if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3030		END_PROFILE(SMBwrite);
3031		return(UNIXERROR(ERRHRD,ERRdiskfull));
3032	}
3033
3034	outsize = set_message(outbuf,1,0,True);
3035
3036	SSVAL(outbuf,smb_vwv0,nwritten);
3037
3038	if (nwritten < (ssize_t)numtowrite) {
3039		SCVAL(outbuf,smb_rcls,ERRHRD);
3040		SSVAL(outbuf,smb_err,ERRdiskfull);
3041	}
3042
3043	DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
3044
3045	END_PROFILE(SMBwrite);
3046	return(outsize);
3047}
3048
3049/****************************************************************************
3050 Reply to a write and X.
3051****************************************************************************/
3052
3053int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3054{
3055	files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3056	SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
3057	size_t numtowrite = SVAL(inbuf,smb_vwv10);
3058	BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
3059	ssize_t nwritten = -1;
3060	unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
3061	unsigned int smblen = smb_len(inbuf);
3062	char *data;
3063	BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
3064	NTSTATUS status;
3065	START_PROFILE(SMBwriteX);
3066
3067	/* If it's an IPC, pass off the pipe handler. */
3068	if (IS_IPC(conn)) {
3069		END_PROFILE(SMBwriteX);
3070		return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
3071	}
3072
3073	CHECK_FSP(fsp,conn);
3074	if (!CHECK_WRITE(fsp)) {
3075		return(ERROR_DOS(ERRDOS,ERRbadaccess));
3076	}
3077
3078	set_message(outbuf,6,0,True);
3079
3080	/* Deal with possible LARGE_WRITEX */
3081	if (large_writeX) {
3082		numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
3083	}
3084
3085	if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
3086		END_PROFILE(SMBwriteX);
3087		return ERROR_DOS(ERRDOS,ERRbadmem);
3088	}
3089
3090	data = smb_base(inbuf) + smb_doff;
3091
3092	if(CVAL(inbuf,smb_wct) == 14) {
3093#ifdef LARGE_SMB_OFF_T
3094		/*
3095		 * This is a large offset (64 bit) write.
3096		 */
3097		startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
3098
3099#else /* !LARGE_SMB_OFF_T */
3100
3101		/*
3102		 * Ensure we haven't been sent a >32 bit offset.
3103		 */
3104
3105		if(IVAL(inbuf,smb_vwv12) != 0) {
3106			DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
310764 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
3108			END_PROFILE(SMBwriteX);
3109			return ERROR_DOS(ERRDOS,ERRbadaccess);
3110		}
3111
3112#endif /* LARGE_SMB_OFF_T */
3113	}
3114
3115	if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3116		END_PROFILE(SMBwriteX);
3117		return ERROR_DOS(ERRDOS,ERRlock);
3118	}
3119
3120	/* X/Open SMB protocol says that, unlike SMBwrite
3121	if the length is zero then NO truncation is
3122	done, just a write of zero. To truncate a file,
3123	use SMBwrite. */
3124
3125	if(numtowrite == 0) {
3126		nwritten = 0;
3127	} else {
3128
3129		if (schedule_aio_write_and_X(conn, inbuf, outbuf, length, bufsize,
3130					fsp,data,startpos,numtowrite)) {
3131			END_PROFILE(SMBwriteX);
3132			return -1;
3133		}
3134
3135		nwritten = write_file(fsp,data,startpos,numtowrite);
3136	}
3137
3138	if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3139		END_PROFILE(SMBwriteX);
3140		return(UNIXERROR(ERRHRD,ERRdiskfull));
3141	}
3142
3143	SSVAL(outbuf,smb_vwv2,nwritten);
3144	if (large_writeX)
3145		SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
3146
3147	if (nwritten < (ssize_t)numtowrite) {
3148		SCVAL(outbuf,smb_rcls,ERRHRD);
3149		SSVAL(outbuf,smb_err,ERRdiskfull);
3150	}
3151
3152	DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
3153		fsp->fnum, (int)numtowrite, (int)nwritten));
3154
3155	status = sync_file(conn, fsp, write_through);
3156	if (!NT_STATUS_IS_OK(status)) {
3157		END_PROFILE(SMBwriteX);
3158		DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
3159			fsp->fsp_name, nt_errstr(status) ));
3160		return ERROR_NT(status);
3161	}
3162
3163	END_PROFILE(SMBwriteX);
3164	return chain_reply(inbuf,outbuf,length,bufsize);
3165}
3166
3167#if defined(HAVE_BCM_RECVFILE)
3168/****************************************************************************
3169 Reply to a write and X usig recvfile.
3170****************************************************************************/
3171
3172int reply_write_and_X_recvfile(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize, size_t *pending_bytes_p)
3173{
3174	files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3175	SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
3176	size_t numtowrite = SVAL(inbuf,smb_vwv10);
3177	BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
3178	ssize_t nwritten = -1;
3179	unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
3180	unsigned int smblen = smb_len(inbuf);
3181	char *data;
3182	BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
3183	NTSTATUS status;
3184	START_PROFILE(SMBwriteX);
3185
3186	/* If it's an IPC, pass off the pipe handler. */
3187	if (IS_IPC(conn)) {
3188		END_PROFILE(SMBwriteX);
3189		return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
3190	}
3191
3192	CHECK_FSP(fsp,conn);
3193	if (!CHECK_WRITE(fsp)) {
3194		return(ERROR_DOS(ERRDOS,ERRbadaccess));
3195	}
3196
3197	set_message(outbuf,6,0,True);
3198
3199	/* Deal with possible LARGE_WRITEX */
3200	if (large_writeX) {
3201		numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 ) << 16);
3202	}
3203
3204	if (smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
3205		END_PROFILE(SMBwriteX);
3206		return ERROR_DOS(ERRDOS,ERRbadmem);
3207	}
3208
3209	data = smb_base(inbuf) + smb_doff;
3210
3211	if (CVAL(inbuf,smb_wct) == 14) {
3212#ifdef LARGE_SMB_OFF_T
3213		/*
3214		 * This is a large offset (64 bit) write.
3215		 */
3216		startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
3217#else /* !LARGE_SMB_OFF_T */
3218		/*
3219		 * Ensure we haven't been sent a >32 bit offset.
3220		 */
3221		if (IVAL(inbuf,smb_vwv12) != 0) {
3222			DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
3223					64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12)));
3224			END_PROFILE(SMBwriteX);
3225			return ERROR_DOS(ERRDOS,ERRbadaccess);
3226		}
3227#endif /* LARGE_SMB_OFF_T */
3228	}
3229
3230	if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3231		END_PROFILE(SMBwriteX);
3232		return ERROR_DOS(ERRDOS,ERRlock);
3233	}
3234
3235	/* X/Open SMB protocol says that, unlike SMBwrite
3236	if the length is zero then NO truncation is
3237	done, just a write of zero. To truncate a file,
3238	use SMBwrite. */
3239
3240	if (numtowrite == 0) {
3241		nwritten = 0;
3242	} else {
3243
3244		if ((*pending_bytes_p == 0) && schedule_aio_write_and_X(conn, inbuf, outbuf, length, bufsize,
3245					fsp,data,startpos,numtowrite)) {
3246			END_PROFILE(SMBwriteX);
3247			return -1;
3248		}
3249
3250		/* CALL recvfile directly from here */
3251		nwritten = sys_recvfile(smbd_server_fd(), fsp->fh->fd,startpos, numtowrite, inbuf+STANDARD_WRITEX_HDR_SIZE);
3252
3253		*pending_bytes_p = numtowrite - nwritten;
3254	}
3255
3256	if (((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3257		END_PROFILE(SMBwriteX);
3258		return(UNIXERROR(ERRHRD,ERRdiskfull));
3259	}
3260
3261	SSVAL(outbuf,smb_vwv2,nwritten);
3262	if (large_writeX)
3263		SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
3264
3265	if (nwritten < (ssize_t)numtowrite) {
3266		SCVAL(outbuf,smb_rcls,ERRHRD);
3267		SSVAL(outbuf,smb_err,ERRdiskfull);
3268	}
3269
3270	DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
3271		fsp->fnum, (int)numtowrite, (int)nwritten));
3272
3273	status = sync_file(conn, fsp, write_through);
3274	if (!NT_STATUS_IS_OK(status)) {
3275		END_PROFILE(SMBwriteX);
3276		DEBUG(5,("reply_write_and_X: sync_file for %s returned %s\n",
3277			fsp->fsp_name, nt_errstr(status) ));
3278		return ERROR_NT(status);
3279	}
3280
3281	END_PROFILE(SMBwriteX);
3282	return chain_reply(inbuf,outbuf,length,bufsize);
3283}
3284#endif /* HAVE_BCM_RECVFILE */
3285
3286/****************************************************************************
3287 Reply to a lseek.
3288****************************************************************************/
3289
3290int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3291{
3292	SMB_OFF_T startpos;
3293	SMB_OFF_T res= -1;
3294	int mode,umode;
3295	int outsize = 0;
3296	files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3297	START_PROFILE(SMBlseek);
3298
3299	CHECK_FSP(fsp,conn);
3300
3301	flush_write_cache(fsp, SEEK_FLUSH);
3302
3303	mode = SVAL(inbuf,smb_vwv1) & 3;
3304	/* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
3305	startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
3306
3307	switch (mode) {
3308		case 0:
3309			umode = SEEK_SET;
3310			res = startpos;
3311			break;
3312		case 1:
3313			umode = SEEK_CUR;
3314			res = fsp->fh->pos + startpos;
3315			break;
3316		case 2:
3317			umode = SEEK_END;
3318			break;
3319		default:
3320			umode = SEEK_SET;
3321			res = startpos;
3322			break;
3323	}
3324
3325	if (umode == SEEK_END) {
3326		if((res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,startpos,umode)) == -1) {
3327			if(errno == EINVAL) {
3328				SMB_OFF_T current_pos = startpos;
3329				SMB_STRUCT_STAT sbuf;
3330
3331				if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
3332					END_PROFILE(SMBlseek);
3333					return(UNIXERROR(ERRDOS,ERRnoaccess));
3334				}
3335
3336				current_pos += sbuf.st_size;
3337				if(current_pos < 0)
3338					res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,0,SEEK_SET);
3339			}
3340		}
3341
3342		if(res == -1) {
3343			END_PROFILE(SMBlseek);
3344			return(UNIXERROR(ERRDOS,ERRnoaccess));
3345		}
3346	}
3347
3348	fsp->fh->pos = res;
3349
3350	outsize = set_message(outbuf,2,0,True);
3351	SIVAL(outbuf,smb_vwv0,res);
3352
3353	DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
3354		fsp->fnum, (double)startpos, (double)res, mode));
3355
3356	END_PROFILE(SMBlseek);
3357	return(outsize);
3358}
3359
3360/****************************************************************************
3361 Reply to a flush.
3362****************************************************************************/
3363
3364int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3365{
3366	int outsize = set_message(outbuf,0,0,False);
3367	uint16 fnum = SVAL(inbuf,smb_vwv0);
3368	files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3369	START_PROFILE(SMBflush);
3370
3371	if (fnum != 0xFFFF)
3372		CHECK_FSP(fsp,conn);
3373
3374	if (!fsp) {
3375		file_sync_all(conn);
3376	} else {
3377		NTSTATUS status = sync_file(conn, fsp, True);
3378		if (!NT_STATUS_IS_OK(status)) {
3379			END_PROFILE(SMBflush);
3380			DEBUG(5,("reply_flush: sync_file for %s returned %s\n",
3381				fsp->fsp_name, nt_errstr(status) ));
3382			return ERROR_NT(status);
3383		}
3384	}
3385
3386	DEBUG(3,("flush\n"));
3387	END_PROFILE(SMBflush);
3388	return(outsize);
3389}
3390
3391/****************************************************************************
3392 Reply to a exit.
3393 conn POINTER CAN BE NULL HERE !
3394****************************************************************************/
3395
3396int reply_exit(connection_struct *conn,
3397	       char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3398{
3399	int outsize;
3400	START_PROFILE(SMBexit);
3401
3402	file_close_pid(SVAL(inbuf,smb_pid),SVAL(inbuf,smb_uid));
3403
3404	outsize = set_message(outbuf,0,0,False);
3405
3406	DEBUG(3,("exit\n"));
3407
3408	END_PROFILE(SMBexit);
3409	return(outsize);
3410}
3411
3412/****************************************************************************
3413 Reply to a close - has to deal with closing a directory opened by NT SMB's.
3414****************************************************************************/
3415
3416int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
3417                int dum_buffsize)
3418{
3419	NTSTATUS status = NT_STATUS_OK;
3420	int outsize = 0;
3421	files_struct *fsp = NULL;
3422	START_PROFILE(SMBclose);
3423
3424	outsize = set_message(outbuf,0,0,False);
3425
3426	/* If it's an IPC, pass off to the pipe handler. */
3427	if (IS_IPC(conn)) {
3428		END_PROFILE(SMBclose);
3429		return reply_pipe_close(conn, inbuf,outbuf);
3430	}
3431
3432	fsp = file_fsp(inbuf,smb_vwv0);
3433
3434	/*
3435	 * We can only use CHECK_FSP if we know it's not a directory.
3436	 */
3437
3438	if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
3439		END_PROFILE(SMBclose);
3440		return ERROR_DOS(ERRDOS,ERRbadfid);
3441	}
3442
3443	if(fsp->is_directory) {
3444		/*
3445		 * Special case - close NT SMB directory handle.
3446		 */
3447		DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
3448		status = close_file(fsp,NORMAL_CLOSE);
3449	} else {
3450		/*
3451		 * Close ordinary file.
3452		 */
3453
3454		DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
3455			 fsp->fh->fd, fsp->fnum,
3456			 conn->num_files_open));
3457
3458		/*
3459		 * Take care of any time sent in the close.
3460		 */
3461
3462		fsp_set_pending_modtime(fsp,
3463				convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv1)));
3464
3465		/*
3466		 * close_file() returns the unix errno if an error
3467		 * was detected on close - normally this is due to
3468		 * a disk full error. If not then it was probably an I/O error.
3469		 */
3470
3471		status = close_file(fsp,NORMAL_CLOSE);
3472	}
3473
3474	if(!NT_STATUS_IS_OK(status)) {
3475		END_PROFILE(SMBclose);
3476		return ERROR_NT(status);
3477	}
3478
3479	END_PROFILE(SMBclose);
3480	return(outsize);
3481}
3482
3483/****************************************************************************
3484 Reply to a writeclose (Core+ protocol).
3485****************************************************************************/
3486
3487int reply_writeclose(connection_struct *conn,
3488		     char *inbuf,char *outbuf, int size, int dum_buffsize)
3489{
3490	size_t numtowrite;
3491	ssize_t nwritten = -1;
3492	int outsize = 0;
3493	NTSTATUS close_status = NT_STATUS_OK;
3494	SMB_OFF_T startpos;
3495	char *data;
3496	struct timespec mtime;
3497	files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3498	START_PROFILE(SMBwriteclose);
3499
3500	CHECK_FSP(fsp,conn);
3501	if (!CHECK_WRITE(fsp)) {
3502		return(ERROR_DOS(ERRDOS,ERRbadaccess));
3503	}
3504
3505	numtowrite = SVAL(inbuf,smb_vwv1);
3506	startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
3507	mtime = convert_time_t_to_timespec(srv_make_unix_date3(inbuf+smb_vwv4));
3508	data = smb_buf(inbuf) + 1;
3509
3510	if (numtowrite && is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
3511		END_PROFILE(SMBwriteclose);
3512		return ERROR_DOS(ERRDOS,ERRlock);
3513	}
3514
3515	nwritten = write_file(fsp,data,startpos,numtowrite);
3516
3517	set_filetime(conn, fsp->fsp_name, mtime);
3518
3519	/*
3520	 * More insanity. W2K only closes the file if writelen > 0.
3521	 * JRA.
3522	 */
3523
3524	if (numtowrite) {
3525		DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
3526			fsp->fsp_name ));
3527		close_status = close_file(fsp,NORMAL_CLOSE);
3528	}
3529
3530	DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
3531		 fsp->fnum, (int)numtowrite, (int)nwritten,
3532		 conn->num_files_open));
3533
3534	if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
3535		END_PROFILE(SMBwriteclose);
3536		return(UNIXERROR(ERRHRD,ERRdiskfull));
3537	}
3538
3539	if(!NT_STATUS_IS_OK(close_status)) {
3540		END_PROFILE(SMBwriteclose);
3541		return ERROR_NT(close_status);
3542	}
3543
3544	outsize = set_message(outbuf,1,0,True);
3545
3546	SSVAL(outbuf,smb_vwv0,nwritten);
3547	END_PROFILE(SMBwriteclose);
3548	return(outsize);
3549}
3550
3551#undef DBGC_CLASS
3552#define DBGC_CLASS DBGC_LOCKING
3553
3554/****************************************************************************
3555 Reply to a lock.
3556****************************************************************************/
3557
3558int reply_lock(connection_struct *conn,
3559	       char *inbuf,char *outbuf, int length, int dum_buffsize)
3560{
3561	int outsize = set_message(outbuf,0,0,False);
3562	SMB_BIG_UINT count,offset;
3563	NTSTATUS status;
3564	files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3565	struct byte_range_lock *br_lck = NULL;
3566
3567	START_PROFILE(SMBlock);
3568
3569	CHECK_FSP(fsp,conn);
3570
3571	release_level_2_oplocks_on_change(fsp);
3572
3573	count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3574	offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3575
3576	DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3577		 fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
3578
3579	br_lck = do_lock(fsp,
3580			(uint32)SVAL(inbuf,smb_pid),
3581			count,
3582			offset,
3583			WRITE_LOCK,
3584			WINDOWS_LOCK,
3585			False, /* Non-blocking lock. */
3586			&status,
3587			NULL);
3588
3589	TALLOC_FREE(br_lck);
3590
3591	if (NT_STATUS_V(status)) {
3592		END_PROFILE(SMBlock);
3593		return ERROR_NT(status);
3594	}
3595
3596	END_PROFILE(SMBlock);
3597	return(outsize);
3598}
3599
3600/****************************************************************************
3601 Reply to a unlock.
3602****************************************************************************/
3603
3604int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
3605		 int dum_buffsize)
3606{
3607	int outsize = set_message(outbuf,0,0,False);
3608	SMB_BIG_UINT count,offset;
3609	NTSTATUS status;
3610	files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3611	START_PROFILE(SMBunlock);
3612
3613	CHECK_FSP(fsp,conn);
3614
3615	count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
3616	offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
3617
3618	status = do_unlock(fsp,
3619			(uint32)SVAL(inbuf,smb_pid),
3620			count,
3621			offset,
3622			WINDOWS_LOCK);
3623
3624	if (NT_STATUS_V(status)) {
3625		END_PROFILE(SMBunlock);
3626		return ERROR_NT(status);
3627	}
3628
3629	DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
3630		    fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
3631
3632	END_PROFILE(SMBunlock);
3633	return(outsize);
3634}
3635
3636#undef DBGC_CLASS
3637#define DBGC_CLASS DBGC_ALL
3638
3639/****************************************************************************
3640 Reply to a tdis.
3641 conn POINTER CAN BE NULL HERE !
3642****************************************************************************/
3643
3644int reply_tdis(connection_struct *conn,
3645	       char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3646{
3647	int outsize = set_message(outbuf,0,0,False);
3648	uint16 vuid;
3649	START_PROFILE(SMBtdis);
3650
3651	vuid = SVAL(inbuf,smb_uid);
3652
3653	if (!conn) {
3654		DEBUG(4,("Invalid connection in tdis\n"));
3655		END_PROFILE(SMBtdis);
3656		return ERROR_DOS(ERRSRV,ERRinvnid);
3657	}
3658
3659	conn->used = False;
3660
3661	close_cnum(conn,vuid);
3662
3663	END_PROFILE(SMBtdis);
3664	return outsize;
3665}
3666
3667/****************************************************************************
3668 Reply to a echo.
3669 conn POINTER CAN BE NULL HERE !
3670****************************************************************************/
3671
3672int reply_echo(connection_struct *conn,
3673	       char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3674{
3675	int smb_reverb = SVAL(inbuf,smb_vwv0);
3676	int seq_num;
3677	unsigned int data_len = smb_buflen(inbuf);
3678	int outsize = set_message(outbuf,1,data_len,True);
3679	START_PROFILE(SMBecho);
3680
3681	if (data_len > BUFFER_SIZE) {
3682		DEBUG(0,("reply_echo: data_len too large.\n"));
3683		END_PROFILE(SMBecho);
3684		return -1;
3685	}
3686
3687	/* copy any incoming data back out */
3688	if (data_len > 0)
3689		memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
3690
3691	if (smb_reverb > 100) {
3692		DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
3693		smb_reverb = 100;
3694	}
3695
3696	for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
3697		SSVAL(outbuf,smb_vwv0,seq_num);
3698
3699		smb_setlen(outbuf,outsize - 4);
3700
3701		show_msg(outbuf);
3702		if (!send_smb(smbd_server_fd(),outbuf))
3703			exit_server_cleanly("reply_echo: send_smb failed.");
3704	}
3705
3706	DEBUG(3,("echo %d times\n", smb_reverb));
3707
3708	smb_echo_count++;
3709
3710	END_PROFILE(SMBecho);
3711	return -1;
3712}
3713
3714/****************************************************************************
3715 Reply to a printopen.
3716****************************************************************************/
3717
3718int reply_printopen(connection_struct *conn,
3719		    char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3720{
3721	int outsize = 0;
3722	files_struct *fsp;
3723	NTSTATUS status;
3724
3725	START_PROFILE(SMBsplopen);
3726
3727	if (!CAN_PRINT(conn)) {
3728		END_PROFILE(SMBsplopen);
3729		return ERROR_DOS(ERRDOS,ERRnoaccess);
3730	}
3731
3732	/* Open for exclusive use, write only. */
3733	status = print_fsp_open(conn, NULL, &fsp);
3734
3735	if (!NT_STATUS_IS_OK(status)) {
3736		END_PROFILE(SMBsplopen);
3737		return(ERROR_NT(status));
3738	}
3739
3740	outsize = set_message(outbuf,1,0,True);
3741	SSVAL(outbuf,smb_vwv0,fsp->fnum);
3742
3743	DEBUG(3,("openprint fd=%d fnum=%d\n",
3744		 fsp->fh->fd, fsp->fnum));
3745
3746	END_PROFILE(SMBsplopen);
3747	return(outsize);
3748}
3749
3750/****************************************************************************
3751 Reply to a printclose.
3752****************************************************************************/
3753
3754int reply_printclose(connection_struct *conn,
3755		     char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3756{
3757	int outsize = set_message(outbuf,0,0,False);
3758	files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3759	NTSTATUS status;
3760	START_PROFILE(SMBsplclose);
3761
3762	CHECK_FSP(fsp,conn);
3763
3764	if (!CAN_PRINT(conn)) {
3765		END_PROFILE(SMBsplclose);
3766		return ERROR_NT(NT_STATUS_DOS(ERRSRV, ERRerror));
3767	}
3768
3769	DEBUG(3,("printclose fd=%d fnum=%d\n",
3770		 fsp->fh->fd,fsp->fnum));
3771
3772	status = close_file(fsp,NORMAL_CLOSE);
3773
3774	if(!NT_STATUS_IS_OK(status)) {
3775		END_PROFILE(SMBsplclose);
3776		return ERROR_NT(status);
3777	}
3778
3779	END_PROFILE(SMBsplclose);
3780	return(outsize);
3781}
3782
3783/****************************************************************************
3784 Reply to a printqueue.
3785****************************************************************************/
3786
3787int reply_printqueue(connection_struct *conn,
3788		     char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3789{
3790	int outsize = set_message(outbuf,2,3,True);
3791	int max_count = SVAL(inbuf,smb_vwv0);
3792	int start_index = SVAL(inbuf,smb_vwv1);
3793	START_PROFILE(SMBsplretq);
3794
3795	/* we used to allow the client to get the cnum wrong, but that
3796	   is really quite gross and only worked when there was only
3797	   one printer - I think we should now only accept it if they
3798	   get it right (tridge) */
3799	if (!CAN_PRINT(conn)) {
3800		END_PROFILE(SMBsplretq);
3801		return ERROR_DOS(ERRDOS,ERRnoaccess);
3802	}
3803
3804	SSVAL(outbuf,smb_vwv0,0);
3805	SSVAL(outbuf,smb_vwv1,0);
3806	SCVAL(smb_buf(outbuf),0,1);
3807	SSVAL(smb_buf(outbuf),1,0);
3808
3809	DEBUG(3,("printqueue start_index=%d max_count=%d\n",
3810		 start_index, max_count));
3811
3812	{
3813		print_queue_struct *queue = NULL;
3814		print_status_struct status;
3815		char *p = smb_buf(outbuf) + 3;
3816		int count = print_queue_status(SNUM(conn), &queue, &status);
3817		int num_to_get = ABS(max_count);
3818		int first = (max_count>0?start_index:start_index+max_count+1);
3819		int i;
3820
3821		if (first >= count)
3822			num_to_get = 0;
3823		else
3824			num_to_get = MIN(num_to_get,count-first);
3825
3826
3827		for (i=first;i<first+num_to_get;i++) {
3828			srv_put_dos_date2(p,0,queue[i].time);
3829			SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
3830			SSVAL(p,5, queue[i].job);
3831			SIVAL(p,7,queue[i].size);
3832			SCVAL(p,11,0);
3833			srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
3834			p += 28;
3835		}
3836
3837		if (count > 0) {
3838			outsize = set_message(outbuf,2,28*count+3,False);
3839			SSVAL(outbuf,smb_vwv0,count);
3840			SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
3841			SCVAL(smb_buf(outbuf),0,1);
3842			SSVAL(smb_buf(outbuf),1,28*count);
3843		}
3844
3845		SAFE_FREE(queue);
3846
3847		DEBUG(3,("%d entries returned in queue\n",count));
3848	}
3849
3850	END_PROFILE(SMBsplretq);
3851	return(outsize);
3852}
3853
3854/****************************************************************************
3855 Reply to a printwrite.
3856****************************************************************************/
3857
3858int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3859{
3860	int numtowrite;
3861	int outsize = set_message(outbuf,0,0,False);
3862	char *data;
3863	files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3864
3865	START_PROFILE(SMBsplwr);
3866
3867	if (!CAN_PRINT(conn)) {
3868		END_PROFILE(SMBsplwr);
3869		return ERROR_DOS(ERRDOS,ERRnoaccess);
3870	}
3871
3872	CHECK_FSP(fsp,conn);
3873	if (!CHECK_WRITE(fsp)) {
3874		return(ERROR_DOS(ERRDOS,ERRbadaccess));
3875	}
3876
3877	numtowrite = SVAL(smb_buf(inbuf),1);
3878	data = smb_buf(inbuf) + 3;
3879
3880	if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
3881		END_PROFILE(SMBsplwr);
3882		return(UNIXERROR(ERRHRD,ERRdiskfull));
3883	}
3884
3885	DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
3886
3887	END_PROFILE(SMBsplwr);
3888	return(outsize);
3889}
3890
3891/****************************************************************************
3892 Reply to a mkdir.
3893****************************************************************************/
3894
3895int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3896{
3897	pstring directory;
3898	int outsize;
3899	NTSTATUS status;
3900	SMB_STRUCT_STAT sbuf;
3901
3902	START_PROFILE(SMBmkdir);
3903
3904	srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
3905	if (!NT_STATUS_IS_OK(status)) {
3906		END_PROFILE(SMBmkdir);
3907		return ERROR_NT(status);
3908	}
3909
3910	status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory);
3911	if (!NT_STATUS_IS_OK(status)) {
3912		END_PROFILE(SMBmkdir);
3913		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3914			return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3915		}
3916		return ERROR_NT(status);
3917	}
3918
3919	status = unix_convert(conn, directory, False, NULL, &sbuf);
3920	if (!NT_STATUS_IS_OK(status)) {
3921		END_PROFILE(SMBmkdir);
3922		return ERROR_NT(status);
3923	}
3924
3925	status = check_name(conn, directory);
3926	if (!NT_STATUS_IS_OK(status)) {
3927		END_PROFILE(SMBmkdir);
3928		return ERROR_NT(status);
3929	}
3930
3931	status = create_directory(conn, directory);
3932
3933	DEBUG(5, ("create_directory returned %s\n", nt_errstr(status)));
3934
3935	if (!NT_STATUS_IS_OK(status)) {
3936
3937		if (!use_nt_status()
3938		    && NT_STATUS_EQUAL(status,
3939				       NT_STATUS_OBJECT_NAME_COLLISION)) {
3940			/*
3941			 * Yes, in the DOS error code case we get a
3942			 * ERRDOS:ERRnoaccess here. See BASE-SAMBA3ERROR
3943			 * samba4 torture test.
3944			 */
3945			status = NT_STATUS_DOS(ERRDOS, ERRnoaccess);
3946		}
3947
3948		END_PROFILE(SMBmkdir);
3949		return ERROR_NT(status);
3950	}
3951
3952	outsize = set_message(outbuf,0,0,False);
3953
3954	DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3955
3956	END_PROFILE(SMBmkdir);
3957	return(outsize);
3958}
3959
3960/****************************************************************************
3961 Static function used by reply_rmdir to delete an entire directory
3962 tree recursively. Return True on ok, False on fail.
3963****************************************************************************/
3964
3965static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3966{
3967	const char *dname = NULL;
3968	BOOL ret = True;
3969	long offset = 0;
3970	struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
3971
3972	if(dir_hnd == NULL)
3973		return False;
3974
3975	while((dname = ReadDirName(dir_hnd, &offset))) {
3976		pstring fullname;
3977		SMB_STRUCT_STAT st;
3978
3979		if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3980			continue;
3981
3982		if (!is_visible_file(conn, directory, dname, &st, False))
3983			continue;
3984
3985		/* Construct the full name. */
3986		if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3987			errno = ENOMEM;
3988			ret = False;
3989			break;
3990		}
3991
3992		pstrcpy(fullname, directory);
3993		pstrcat(fullname, "/");
3994		pstrcat(fullname, dname);
3995
3996		if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3997			ret = False;
3998			break;
3999		}
4000
4001		if(st.st_mode & S_IFDIR) {
4002			if(!recursive_rmdir(conn, fullname)) {
4003				ret = False;
4004				break;
4005			}
4006			if(SMB_VFS_RMDIR(conn,fullname) != 0) {
4007				ret = False;
4008				break;
4009			}
4010		} else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
4011			ret = False;
4012			break;
4013		}
4014	}
4015	CloseDir(dir_hnd);
4016	return ret;
4017}
4018
4019/****************************************************************************
4020 The internals of the rmdir code - called elsewhere.
4021****************************************************************************/
4022
4023NTSTATUS rmdir_internals(connection_struct *conn, const char *directory)
4024{
4025	int ret;
4026	SMB_STRUCT_STAT st;
4027
4028	/* Might be a symlink. */
4029	if(SMB_VFS_LSTAT(conn, directory, &st) != 0) {
4030		return map_nt_error_from_unix(errno);
4031	}
4032
4033	if (S_ISLNK(st.st_mode)) {
4034		/* Is what it points to a directory ? */
4035		if(SMB_VFS_STAT(conn, directory, &st) != 0) {
4036			return map_nt_error_from_unix(errno);
4037		}
4038		if (!(S_ISDIR(st.st_mode))) {
4039			return NT_STATUS_NOT_A_DIRECTORY;
4040		}
4041		ret = SMB_VFS_UNLINK(conn,directory);
4042	} else {
4043		ret = SMB_VFS_RMDIR(conn,directory);
4044	}
4045	if (ret == 0) {
4046		notify_fname(conn, NOTIFY_ACTION_REMOVED,
4047			     FILE_NOTIFY_CHANGE_DIR_NAME,
4048			     directory);
4049		return NT_STATUS_OK;
4050	}
4051
4052	if(((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
4053		/*
4054		 * Check to see if the only thing in this directory are
4055		 * vetoed files/directories. If so then delete them and
4056		 * retry. If we fail to delete any of them (and we *don't*
4057		 * do a recursive delete) then fail the rmdir.
4058		 */
4059		const char *dname;
4060		long dirpos = 0;
4061		struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
4062
4063		if(dir_hnd == NULL) {
4064			errno = ENOTEMPTY;
4065			goto err;
4066		}
4067
4068		while ((dname = ReadDirName(dir_hnd,&dirpos))) {
4069			if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4070				continue;
4071			if (!is_visible_file(conn, directory, dname, &st, False))
4072				continue;
4073			if(!IS_VETO_PATH(conn, dname)) {
4074				CloseDir(dir_hnd);
4075				errno = ENOTEMPTY;
4076				goto err;
4077			}
4078		}
4079
4080		/* We only have veto files/directories. Recursive delete. */
4081
4082		RewindDir(dir_hnd,&dirpos);
4083		while ((dname = ReadDirName(dir_hnd,&dirpos))) {
4084			pstring fullname;
4085
4086			if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
4087				continue;
4088			if (!is_visible_file(conn, directory, dname, &st, False))
4089				continue;
4090
4091			/* Construct the full name. */
4092			if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
4093				errno = ENOMEM;
4094				break;
4095			}
4096
4097			pstrcpy(fullname, directory);
4098			pstrcat(fullname, "/");
4099			pstrcat(fullname, dname);
4100
4101			if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
4102				break;
4103			if(st.st_mode & S_IFDIR) {
4104				if(lp_recursive_veto_delete(SNUM(conn))) {
4105					if(!recursive_rmdir(conn, fullname))
4106						break;
4107				}
4108				if(SMB_VFS_RMDIR(conn,fullname) != 0)
4109					break;
4110			} else if(SMB_VFS_UNLINK(conn,fullname) != 0)
4111				break;
4112		}
4113		CloseDir(dir_hnd);
4114		/* Retry the rmdir */
4115		ret = SMB_VFS_RMDIR(conn,directory);
4116	}
4117
4118  err:
4119
4120	if (ret != 0) {
4121		DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
4122			 "%s\n", directory,strerror(errno)));
4123		return map_nt_error_from_unix(errno);
4124	}
4125
4126	notify_fname(conn, NOTIFY_ACTION_REMOVED,
4127		     FILE_NOTIFY_CHANGE_DIR_NAME,
4128		     directory);
4129
4130	return NT_STATUS_OK;
4131}
4132
4133/****************************************************************************
4134 Reply to a rmdir.
4135****************************************************************************/
4136
4137int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4138{
4139	pstring directory;
4140	int outsize = 0;
4141	SMB_STRUCT_STAT sbuf;
4142	NTSTATUS status;
4143	START_PROFILE(SMBrmdir);
4144
4145	srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
4146	if (!NT_STATUS_IS_OK(status)) {
4147		END_PROFILE(SMBrmdir);
4148		return ERROR_NT(status);
4149	}
4150
4151	status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory);
4152	if (!NT_STATUS_IS_OK(status)) {
4153		END_PROFILE(SMBrmdir);
4154		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4155			return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
4156		}
4157		return ERROR_NT(status);
4158	}
4159
4160	status = unix_convert(conn, directory, False, NULL, &sbuf);
4161	if (!NT_STATUS_IS_OK(status)) {
4162		END_PROFILE(SMBrmdir);
4163		return ERROR_NT(status);
4164	}
4165
4166	status = check_name(conn, directory);
4167	if (!NT_STATUS_IS_OK(status)) {
4168		END_PROFILE(SMBrmdir);
4169		return ERROR_NT(status);
4170	}
4171
4172	dptr_closepath(directory,SVAL(inbuf,smb_pid));
4173	status = rmdir_internals(conn, directory);
4174	if (!NT_STATUS_IS_OK(status)) {
4175		END_PROFILE(SMBrmdir);
4176		return ERROR_NT(status);
4177	}
4178
4179	outsize = set_message(outbuf,0,0,False);
4180
4181	DEBUG( 3, ( "rmdir %s\n", directory ) );
4182
4183	END_PROFILE(SMBrmdir);
4184	return(outsize);
4185}
4186
4187/*******************************************************************
4188 Resolve wildcards in a filename rename.
4189 Note that name is in UNIX charset and thus potentially can be more
4190 than fstring buffer (255 bytes) especially in default UTF-8 case.
4191 Therefore, we use pstring inside and all calls should ensure that
4192 name2 is at least pstring-long (they do already)
4193********************************************************************/
4194
4195static BOOL resolve_wildcards(const char *name1, char *name2)
4196{
4197	pstring root1,root2;
4198	pstring ext1,ext2;
4199	char *p,*p2, *pname1, *pname2;
4200	int available_space, actual_space;
4201
4202	pname1 = strrchr_m(name1,'/');
4203	pname2 = strrchr_m(name2,'/');
4204
4205	if (!pname1 || !pname2)
4206		return(False);
4207
4208	pstrcpy(root1,pname1);
4209	pstrcpy(root2,pname2);
4210	p = strrchr_m(root1,'.');
4211	if (p) {
4212		*p = 0;
4213		pstrcpy(ext1,p+1);
4214	} else {
4215		pstrcpy(ext1,"");
4216	}
4217	p = strrchr_m(root2,'.');
4218	if (p) {
4219		*p = 0;
4220		pstrcpy(ext2,p+1);
4221	} else {
4222		pstrcpy(ext2,"");
4223	}
4224
4225	p = root1;
4226	p2 = root2;
4227	while (*p2) {
4228		if (*p2 == '?') {
4229			*p2 = *p;
4230			p2++;
4231		} else if (*p2 == '*') {
4232			pstrcpy(p2, p);
4233			break;
4234		} else {
4235			p2++;
4236		}
4237		if (*p)
4238			p++;
4239	}
4240
4241	p = ext1;
4242	p2 = ext2;
4243	while (*p2) {
4244		if (*p2 == '?') {
4245			*p2 = *p;
4246			p2++;
4247		} else if (*p2 == '*') {
4248			pstrcpy(p2, p);
4249			break;
4250		} else {
4251			p2++;
4252		}
4253		if (*p)
4254			p++;
4255	}
4256
4257	available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
4258
4259	if (ext2[0]) {
4260		actual_space = snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
4261		if (actual_space >= available_space - 1) {
4262			DEBUG(1,("resolve_wildcards: can't fit resolved name into specified buffer (overrun by %d bytes)\n",
4263				actual_space - available_space));
4264		}
4265	} else {
4266		pstrcpy_base(pname2, root2, name2);
4267	}
4268
4269	return(True);
4270}
4271
4272/****************************************************************************
4273 Ensure open files have their names updated. Updated to notify other smbd's
4274 asynchronously.
4275****************************************************************************/
4276
4277static void rename_open_files(connection_struct *conn, struct share_mode_lock *lck,
4278				SMB_DEV_T dev, SMB_INO_T inode, const char *newname)
4279{
4280	files_struct *fsp;
4281	BOOL did_rename = False;
4282
4283	for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
4284		/* fsp_name is a relative path under the fsp. To change this for other
4285		   sharepaths we need to manipulate relative paths. */
4286		/* TODO - create the absolute path and manipulate the newname
4287		   relative to the sharepath. */
4288		if (fsp->conn != conn) {
4289			continue;
4290		}
4291		DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
4292			fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
4293			fsp->fsp_name, newname ));
4294		string_set(&fsp->fsp_name, newname);
4295		did_rename = True;
4296	}
4297
4298	if (!did_rename) {
4299		DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
4300			(unsigned int)dev, (double)inode, newname ));
4301	}
4302
4303	/* Send messages to all smbd's (not ourself) that the name has changed. */
4304	rename_share_filename(lck, conn->connectpath, newname);
4305}
4306
4307/****************************************************************************
4308 We need to check if the source path is a parent directory of the destination
4309 (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
4310 refuse the rename with a sharing violation. Under UNIX the above call can
4311 *succeed* if /foo/bar/baz is a symlink to another area in the share. We
4312 probably need to check that the client is a Windows one before disallowing
4313 this as a UNIX client (one with UNIX extensions) can know the source is a
4314 symlink and make this decision intelligently. Found by an excellent bug
4315 report from <AndyLiebman@aol.com>.
4316****************************************************************************/
4317
4318static BOOL rename_path_prefix_equal(const char *src, const char *dest)
4319{
4320	const char *psrc = src;
4321	const char *pdst = dest;
4322	size_t slen;
4323
4324	if (psrc[0] == '.' && psrc[1] == '/') {
4325		psrc += 2;
4326	}
4327	if (pdst[0] == '.' && pdst[1] == '/') {
4328		pdst += 2;
4329	}
4330	if ((slen = strlen(psrc)) > strlen(pdst)) {
4331		return False;
4332	}
4333	return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
4334}
4335
4336/****************************************************************************
4337 Rename an open file - given an fsp.
4338****************************************************************************/
4339
4340NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstring newname, uint32 attrs, BOOL replace_if_exists)
4341{
4342	SMB_STRUCT_STAT sbuf;
4343	pstring newname_last_component;
4344	NTSTATUS status = NT_STATUS_OK;
4345	BOOL dest_exists;
4346	struct share_mode_lock *lck = NULL;
4347
4348	ZERO_STRUCT(sbuf);
4349
4350	status = unix_convert(conn, newname, False, newname_last_component, &sbuf);
4351
4352	/* If an error we expect this to be NT_STATUS_OBJECT_PATH_NOT_FOUND */
4353
4354	if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND, status)) {
4355		return status;
4356	}
4357
4358	status = check_name(conn, newname);
4359	if (!NT_STATUS_IS_OK(status)) {
4360		return status;
4361	}
4362
4363	/* Ensure newname contains a '/' */
4364	if(strrchr_m(newname,'/') == 0) {
4365		pstring tmpstr;
4366
4367		pstrcpy(tmpstr, "./");
4368		pstrcat(tmpstr, newname);
4369		pstrcpy(newname, tmpstr);
4370	}
4371
4372	/*
4373	 * Check for special case with case preserving and not
4374	 * case sensitive. If the old last component differs from the original
4375	 * last component only by case, then we should allow
4376	 * the rename (user is trying to change the case of the
4377	 * filename).
4378	 */
4379
4380	if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
4381			strequal(newname, fsp->fsp_name)) {
4382		char *p;
4383		pstring newname_modified_last_component;
4384
4385		/*
4386		 * Get the last component of the modified name.
4387		 * Note that we guarantee that newname contains a '/'
4388		 * character above.
4389		 */
4390		p = strrchr_m(newname,'/');
4391		pstrcpy(newname_modified_last_component,p+1);
4392
4393		if(strcsequal(newname_modified_last_component,
4394			      newname_last_component) == False) {
4395			/*
4396			 * Replace the modified last component with
4397			 * the original.
4398			 */
4399			pstrcpy(p+1, newname_last_component);
4400		}
4401	}
4402
4403	/*
4404	 * If the src and dest names are identical - including case,
4405	 * don't do the rename, just return success.
4406	 */
4407
4408	if (strcsequal(fsp->fsp_name, newname)) {
4409		DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
4410			newname));
4411		return NT_STATUS_OK;
4412	}
4413
4414	dest_exists = vfs_object_exist(conn,newname,NULL);
4415
4416	if(!replace_if_exists && dest_exists) {
4417		DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
4418			fsp->fsp_name,newname));
4419		return NT_STATUS_OBJECT_NAME_COLLISION;
4420	}
4421
4422	/* Ensure we have a valid stat struct for the source. */
4423	if (fsp->fh->fd != -1) {
4424		if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) == -1) {
4425			return map_nt_error_from_unix(errno);
4426		}
4427	} else {
4428		if (SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) == -1) {
4429			return map_nt_error_from_unix(errno);
4430		}
4431	}
4432
4433	status = can_rename(conn,fsp->fsp_name,attrs,&sbuf,True);
4434
4435	if (!NT_STATUS_IS_OK(status)) {
4436		DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4437			nt_errstr(status), fsp->fsp_name,newname));
4438		if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION))
4439			status = NT_STATUS_ACCESS_DENIED;
4440		return status;
4441	}
4442
4443	if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
4444		return NT_STATUS_ACCESS_DENIED;
4445	}
4446
4447	lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
4448
4449	if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
4450		uint32 create_options = fsp->fh->private_options;
4451
4452		DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
4453			fsp->fsp_name,newname));
4454
4455		rename_open_files(conn, lck, fsp->dev, fsp->inode, newname);
4456
4457		/*
4458		 * A rename acts as a new file create w.r.t. allowing an initial delete
4459		 * on close, probably because in Windows there is a new handle to the
4460		 * new file. If initial delete on close was requested but not
4461		 * originally set, we need to set it here. This is probably not 100% correct,
4462		 * but will work for the CIFSFS client which in non-posix mode
4463		 * depends on these semantics. JRA.
4464		 */
4465
4466		set_allow_initial_delete_on_close(lck, fsp, True);
4467
4468		if (create_options & FILE_DELETE_ON_CLOSE) {
4469			status = can_set_delete_on_close(fsp, True, 0);
4470
4471			if (NT_STATUS_IS_OK(status)) {
4472				/* Note that here we set the *inital* delete on close flag,
4473				 * not the regular one. The magic gets handled in close. */
4474				fsp->initial_delete_on_close = True;
4475			}
4476		}
4477		TALLOC_FREE(lck);
4478		return NT_STATUS_OK;
4479	}
4480
4481	TALLOC_FREE(lck);
4482
4483	if (errno == ENOTDIR || errno == EISDIR) {
4484		status = NT_STATUS_OBJECT_NAME_COLLISION;
4485	} else {
4486		status = map_nt_error_from_unix(errno);
4487	}
4488
4489	DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
4490		nt_errstr(status), fsp->fsp_name,newname));
4491
4492	return status;
4493}
4494
4495/*
4496 * Do the notify calls from a rename
4497 */
4498
4499static void notify_rename(connection_struct *conn, BOOL is_dir,
4500			  const char *oldpath, const char *newpath)
4501{
4502	char *olddir, *newdir;
4503	const char *oldname, *newname;
4504	uint32 mask;
4505
4506	mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
4507		: FILE_NOTIFY_CHANGE_FILE_NAME;
4508
4509	if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname)
4510	    || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) {
4511		TALLOC_FREE(olddir);
4512		return;
4513	}
4514
4515	if (strcmp(olddir, newdir) == 0) {
4516		notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
4517		notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
4518	}
4519	else {
4520		notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
4521		notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
4522	}
4523	TALLOC_FREE(olddir);
4524	TALLOC_FREE(newdir);
4525
4526	/* this is a strange one. w2k3 gives an additional event for
4527	   CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
4528	   files, but not directories */
4529	if (!is_dir) {
4530		notify_fname(conn, NOTIFY_ACTION_MODIFIED,
4531			     FILE_NOTIFY_CHANGE_ATTRIBUTES
4532			     |FILE_NOTIFY_CHANGE_CREATION,
4533			     newpath);
4534	}
4535}
4536
4537/****************************************************************************
4538 The guts of the rename command, split out so it may be called by the NT SMB
4539 code.
4540****************************************************************************/
4541
4542NTSTATUS rename_internals(connection_struct *conn,
4543				pstring name,
4544				pstring newname,
4545				uint32 attrs,
4546				BOOL replace_if_exists,
4547				BOOL src_has_wild,
4548				BOOL dest_has_wild)
4549{
4550	pstring directory;
4551	pstring mask;
4552	pstring last_component_src;
4553	pstring last_component_dest;
4554	char *p;
4555	int count=0;
4556	NTSTATUS status = NT_STATUS_OK;
4557	SMB_STRUCT_STAT sbuf1, sbuf2;
4558	struct share_mode_lock *lck = NULL;
4559	struct smb_Dir *dir_hnd = NULL;
4560	const char *dname;
4561	long offset = 0;
4562	pstring destname;
4563
4564	*directory = *mask = 0;
4565
4566	ZERO_STRUCT(sbuf1);
4567	ZERO_STRUCT(sbuf2);
4568
4569	status = unix_convert(conn, name, src_has_wild, last_component_src, &sbuf1);
4570	if (!NT_STATUS_IS_OK(status)) {
4571		return status;
4572	}
4573
4574	status = unix_convert(conn, newname, dest_has_wild, last_component_dest, &sbuf2);
4575	if (!NT_STATUS_IS_OK(status)) {
4576		return status;
4577	}
4578
4579	/*
4580	 * Split the old name into directory and last component
4581	 * strings. Note that unix_convert may have stripped off a
4582	 * leading ./ from both name and newname if the rename is
4583	 * at the root of the share. We need to make sure either both
4584	 * name and newname contain a / character or neither of them do
4585	 * as this is checked in resolve_wildcards().
4586	 */
4587
4588	p = strrchr_m(name,'/');
4589	if (!p) {
4590		pstrcpy(directory,".");
4591		pstrcpy(mask,name);
4592	} else {
4593		*p = 0;
4594		pstrcpy(directory,name);
4595		pstrcpy(mask,p+1);
4596		*p = '/'; /* Replace needed for exceptional test below. */
4597	}
4598
4599	/*
4600	 * We should only check the mangled cache
4601	 * here if unix_convert failed. This means
4602	 * that the path in 'mask' doesn't exist
4603	 * on the file system and so we need to look
4604	 * for a possible mangle. This patch from
4605	 * Tine Smukavec <valentin.smukavec@hermes.si>.
4606	 */
4607
4608	if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
4609		mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
4610	}
4611
4612	if (!src_has_wild) {
4613		/*
4614		 * No wildcards - just process the one file.
4615		 */
4616		BOOL is_short_name = mangle_is_8_3(name, True, conn->params);
4617
4618		/* Add a terminating '/' to the directory name. */
4619		pstrcat(directory,"/");
4620		pstrcat(directory,mask);
4621
4622		/* Ensure newname contains a '/' also */
4623		if(strrchr_m(newname,'/') == 0) {
4624			pstring tmpstr;
4625
4626			pstrcpy(tmpstr, "./");
4627			pstrcat(tmpstr, newname);
4628			pstrcpy(newname, tmpstr);
4629		}
4630
4631		DEBUG(3, ("rename_internals: case_sensitive = %d, "
4632			  "case_preserve = %d, short case preserve = %d, "
4633			  "directory = %s, newname = %s, "
4634			  "last_component_dest = %s, is_8_3 = %d\n",
4635			  conn->case_sensitive, conn->case_preserve,
4636			  conn->short_case_preserve, directory,
4637			  newname, last_component_dest, is_short_name));
4638
4639		/* Ensure the source name is valid for us to access. */
4640		status = check_name(conn, directory);
4641		if (!NT_STATUS_IS_OK(status)) {
4642			return status;
4643		}
4644
4645		/* The dest name still may have wildcards. */
4646		if (dest_has_wild) {
4647			if (!resolve_wildcards(directory,newname)) {
4648				DEBUG(6, ("rename_internals: resolve_wildcards %s %s failed\n",
4649					  directory,newname));
4650				return NT_STATUS_NO_MEMORY;
4651			}
4652		}
4653
4654		/*
4655		 * Check for special case with case preserving and not
4656		 * case sensitive, if directory and newname are identical,
4657		 * and the old last component differs from the original
4658		 * last component only by case, then we should allow
4659		 * the rename (user is trying to change the case of the
4660		 * filename).
4661		 */
4662		if((conn->case_sensitive == False) &&
4663		   (((conn->case_preserve == True) &&
4664		     (is_short_name == False)) ||
4665		    ((conn->short_case_preserve == True) &&
4666		     (is_short_name == True))) &&
4667		   strcsequal(directory, newname)) {
4668			pstring modified_last_component;
4669
4670			/*
4671			 * Get the last component of the modified name.
4672			 * Note that we guarantee that newname contains a '/'
4673			 * character above.
4674			 */
4675			p = strrchr_m(newname,'/');
4676			pstrcpy(modified_last_component,p+1);
4677
4678			if(strcsequal(modified_last_component,
4679				      last_component_dest) == False) {
4680				/*
4681				 * Replace the modified last component with
4682				 * the original.
4683				 */
4684				pstrcpy(p+1, last_component_dest);
4685			}
4686		}
4687
4688		/* Ensure the dest name is valid for us to access. */
4689		status = check_name(conn, newname);
4690		if (!NT_STATUS_IS_OK(status)) {
4691			return status;
4692		}
4693
4694		/*
4695		 * The source object must exist.
4696		 */
4697
4698		if (!vfs_object_exist(conn, directory, &sbuf1)) {
4699			DEBUG(3, ("rename_internals: source doesn't exist "
4700				  "doing rename %s -> %s\n",
4701				directory,newname));
4702
4703			if (errno == ENOTDIR || errno == EISDIR
4704			    || errno == ENOENT) {
4705				/*
4706				 * Must return different errors depending on
4707				 * whether the parent directory existed or
4708				 * not.
4709				 */
4710
4711				p = strrchr_m(directory, '/');
4712				if (!p)
4713					return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4714				*p = '\0';
4715				if (vfs_object_exist(conn, directory, NULL))
4716					return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4717				return NT_STATUS_OBJECT_PATH_NOT_FOUND;
4718			}
4719			status = map_nt_error_from_unix(errno);
4720			DEBUG(3, ("rename_internals: Error %s rename %s -> "
4721				  "%s\n", nt_errstr(status), directory,
4722				  newname));
4723
4724			return status;
4725		}
4726
4727		status = can_rename(conn,directory,attrs,&sbuf1,False);
4728
4729		if (!NT_STATUS_IS_OK(status)) {
4730			DEBUG(3,("rename_internals: Error %s rename %s -> "
4731				 "%s\n", nt_errstr(status), directory,
4732				 newname));
4733			return status;
4734		}
4735
4736		/*
4737		 * If the src and dest names are identical - including case,
4738		 * don't do the rename, just return success.
4739		 */
4740
4741		if (strcsequal(directory, newname)) {
4742			DEBUG(3, ("rename_internals: identical names in "
4743				  "rename %s - returning success\n",
4744				  directory));
4745			return NT_STATUS_OK;
4746		}
4747
4748		if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
4749			DEBUG(3,("rename_internals: dest exists doing "
4750				 "rename %s -> %s\n", directory, newname));
4751			return NT_STATUS_OBJECT_NAME_COLLISION;
4752		}
4753
4754		if (rename_path_prefix_equal(directory, newname)) {
4755			return NT_STATUS_SHARING_VIOLATION;
4756		}
4757
4758		lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino,
4759					  NULL, NULL);
4760
4761		if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
4762			DEBUG(3,("rename_internals: succeeded doing rename "
4763				 "on %s -> %s\n", directory, newname));
4764			rename_open_files(conn, lck, sbuf1.st_dev,
4765					  sbuf1.st_ino, newname);
4766			TALLOC_FREE(lck);
4767			notify_rename(conn, S_ISDIR(sbuf1.st_mode),
4768				      directory, newname);
4769			return NT_STATUS_OK;
4770		}
4771
4772		TALLOC_FREE(lck);
4773		if (errno == ENOTDIR || errno == EISDIR) {
4774			status = NT_STATUS_OBJECT_NAME_COLLISION;
4775		} else {
4776			status = map_nt_error_from_unix(errno);
4777		}
4778
4779		DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
4780			nt_errstr(status), directory,newname));
4781
4782		return status;
4783	}
4784
4785	/*
4786	 * Wildcards - process each file that matches.
4787	 */
4788	if (strequal(mask,"????????.???")) {
4789		pstrcpy(mask,"*");
4790	}
4791
4792	status = check_name(conn, directory);
4793	if (!NT_STATUS_IS_OK(status)) {
4794		return status;
4795	}
4796
4797	dir_hnd = OpenDir(conn, directory, mask, attrs);
4798	if (dir_hnd == NULL) {
4799		return map_nt_error_from_unix(errno);
4800	}
4801
4802	status = NT_STATUS_NO_SUCH_FILE;
4803	/*
4804	 * Was status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4805	 * - gentest fix. JRA
4806	 */
4807
4808	while ((dname = ReadDirName(dir_hnd, &offset))) {
4809		pstring fname;
4810		BOOL sysdir_entry = False;
4811
4812		pstrcpy(fname,dname);
4813
4814		/* Quick check for "." and ".." */
4815		if (fname[0] == '.') {
4816			if (!fname[1] || (fname[1] == '.' && !fname[2])) {
4817				if (attrs & aDIR) {
4818					sysdir_entry = True;
4819				} else {
4820					continue;
4821				}
4822			}
4823		}
4824
4825		if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
4826			continue;
4827		}
4828
4829		if(!mask_match(fname, mask, conn->case_sensitive)) {
4830			continue;
4831		}
4832
4833		if (sysdir_entry) {
4834			status = NT_STATUS_OBJECT_NAME_INVALID;
4835			break;
4836		}
4837
4838		status = NT_STATUS_ACCESS_DENIED;
4839		slprintf(fname, sizeof(fname)-1, "%s/%s", directory, dname);
4840
4841		/* Ensure the source name is valid for us to access. */
4842		status = check_name(conn, fname);
4843		if (!NT_STATUS_IS_OK(status)) {
4844			return status;
4845		}
4846
4847		if (!vfs_object_exist(conn, fname, &sbuf1)) {
4848			status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4849			DEBUG(6, ("rename %s failed. Error %s\n",
4850				  fname, nt_errstr(status)));
4851			continue;
4852		}
4853		status = can_rename(conn,fname,attrs,&sbuf1,False);
4854		if (!NT_STATUS_IS_OK(status)) {
4855			DEBUG(6, ("rename %s refused\n", fname));
4856			continue;
4857		}
4858		pstrcpy(destname,newname);
4859
4860		if (!resolve_wildcards(fname,destname)) {
4861			DEBUG(6, ("resolve_wildcards %s %s failed\n",
4862				  fname, destname));
4863			continue;
4864		}
4865
4866		/* Ensure the dest name is valid for us to access. */
4867		status = check_name(conn, destname);
4868		if (!NT_STATUS_IS_OK(status)) {
4869			return status;
4870		}
4871
4872		if (strcsequal(fname,destname)) {
4873			DEBUG(3,("rename_internals: identical names "
4874				 "in wildcard rename %s - success\n",
4875				 fname));
4876			count++;
4877			status = NT_STATUS_OK;
4878			continue;
4879		}
4880
4881		if (!replace_if_exists && vfs_file_exist(conn,destname, NULL)) {
4882			DEBUG(6,("file_exist %s\n", destname));
4883			status = NT_STATUS_OBJECT_NAME_COLLISION;
4884			continue;
4885		}
4886
4887		if (rename_path_prefix_equal(fname, destname)) {
4888			return NT_STATUS_SHARING_VIOLATION;
4889		}
4890
4891		lck = get_share_mode_lock(NULL, sbuf1.st_dev,
4892					  sbuf1.st_ino, NULL, NULL);
4893
4894		if (!SMB_VFS_RENAME(conn,fname,destname)) {
4895			rename_open_files(conn, lck, sbuf1.st_dev,
4896					  sbuf1.st_ino, newname);
4897			count++;
4898			status = NT_STATUS_OK;
4899		}
4900		TALLOC_FREE(lck);
4901		DEBUG(3,("rename_internals: doing rename on %s -> "
4902			 "%s\n",fname,destname));
4903	}
4904	CloseDir(dir_hnd);
4905
4906	if (count == 0 && NT_STATUS_IS_OK(status)) {
4907		status = map_nt_error_from_unix(errno);
4908	}
4909
4910	return status;
4911}
4912
4913/****************************************************************************
4914 Reply to a mv.
4915****************************************************************************/
4916
4917int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
4918	     int dum_buffsize)
4919{
4920	int outsize = 0;
4921	pstring name;
4922	pstring newname;
4923	char *p;
4924	uint32 attrs = SVAL(inbuf,smb_vwv0);
4925	NTSTATUS status;
4926	BOOL src_has_wcard = False;
4927	BOOL dest_has_wcard = False;
4928
4929	START_PROFILE(SMBmv);
4930
4931	p = smb_buf(inbuf) + 1;
4932	p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &src_has_wcard);
4933	if (!NT_STATUS_IS_OK(status)) {
4934		END_PROFILE(SMBmv);
4935		return ERROR_NT(status);
4936	}
4937	p++;
4938	p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wcard);
4939	if (!NT_STATUS_IS_OK(status)) {
4940		END_PROFILE(SMBmv);
4941		return ERROR_NT(status);
4942	}
4943
4944	status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &src_has_wcard);
4945	if (!NT_STATUS_IS_OK(status)) {
4946		END_PROFILE(SMBmv);
4947		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4948			return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
4949		}
4950		return ERROR_NT(status);
4951	}
4952
4953	status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
4954	if (!NT_STATUS_IS_OK(status)) {
4955		END_PROFILE(SMBmv);
4956		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4957			return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
4958		}
4959		return ERROR_NT(status);
4960	}
4961
4962	DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
4963
4964	status = rename_internals(conn, name, newname, attrs, False, src_has_wcard, dest_has_wcard);
4965	if (!NT_STATUS_IS_OK(status)) {
4966		END_PROFILE(SMBmv);
4967		if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4968			/* We have re-scheduled this call. */
4969			return -1;
4970		}
4971		return ERROR_NT(status);
4972	}
4973
4974	outsize = set_message(outbuf,0,0,False);
4975
4976	END_PROFILE(SMBmv);
4977	return(outsize);
4978}
4979
4980/*******************************************************************
4981 Copy a file as part of a reply_copy.
4982******************************************************************/
4983
4984/*
4985 * TODO: check error codes on all callers
4986 */
4987
4988NTSTATUS copy_file(connection_struct *conn,
4989			char *src,
4990			char *dest1,
4991			int ofun,
4992			int count,
4993			BOOL target_is_directory)
4994{
4995	SMB_STRUCT_STAT src_sbuf, sbuf2;
4996	SMB_OFF_T ret=-1;
4997	files_struct *fsp1,*fsp2;
4998	pstring dest;
4999 	uint32 dosattrs;
5000	uint32 new_create_disposition;
5001	NTSTATUS status;
5002
5003	pstrcpy(dest,dest1);
5004	if (target_is_directory) {
5005		char *p = strrchr_m(src,'/');
5006		if (p) {
5007			p++;
5008		} else {
5009			p = src;
5010		}
5011		pstrcat(dest,"/");
5012		pstrcat(dest,p);
5013	}
5014
5015	if (!vfs_file_exist(conn,src,&src_sbuf)) {
5016		return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5017	}
5018
5019	if (!target_is_directory && count) {
5020		new_create_disposition = FILE_OPEN;
5021	} else {
5022		if (!map_open_params_to_ntcreate(dest1,0,ofun,
5023				NULL, NULL, &new_create_disposition, NULL)) {
5024			return NT_STATUS_INVALID_PARAMETER;
5025		}
5026	}
5027
5028	status = open_file_ntcreate(conn,src,&src_sbuf,
5029			FILE_GENERIC_READ,
5030			FILE_SHARE_READ|FILE_SHARE_WRITE,
5031			FILE_OPEN,
5032			0,
5033			FILE_ATTRIBUTE_NORMAL,
5034			INTERNAL_OPEN_ONLY,
5035			NULL, &fsp1);
5036
5037	if (!NT_STATUS_IS_OK(status)) {
5038		return status;
5039	}
5040
5041	dosattrs = dos_mode(conn, src, &src_sbuf);
5042	if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
5043		ZERO_STRUCTP(&sbuf2);
5044	}
5045
5046	status = open_file_ntcreate(conn,dest,&sbuf2,
5047			FILE_GENERIC_WRITE,
5048			FILE_SHARE_READ|FILE_SHARE_WRITE,
5049			new_create_disposition,
5050			0,
5051			dosattrs,
5052			INTERNAL_OPEN_ONLY,
5053			NULL, &fsp2);
5054
5055	if (!NT_STATUS_IS_OK(status)) {
5056		close_file(fsp1,ERROR_CLOSE);
5057		return status;
5058	}
5059
5060	if ((ofun&3) == 1) {
5061		if(SMB_VFS_LSEEK(fsp2,fsp2->fh->fd,0,SEEK_END) == -1) {
5062			DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
5063			/*
5064			 * Stop the copy from occurring.
5065			 */
5066			ret = -1;
5067			src_sbuf.st_size = 0;
5068		}
5069	}
5070
5071	if (src_sbuf.st_size) {
5072		ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
5073	}
5074
5075	close_file(fsp1,NORMAL_CLOSE);
5076
5077	/* Ensure the modtime is set correctly on the destination file. */
5078	fsp_set_pending_modtime( fsp2, get_mtimespec(&src_sbuf));
5079
5080	/*
5081	 * As we are opening fsp1 read-only we only expect
5082	 * an error on close on fsp2 if we are out of space.
5083	 * Thus we don't look at the error return from the
5084	 * close of fsp1.
5085	 */
5086	status = close_file(fsp2,NORMAL_CLOSE);
5087
5088	if (!NT_STATUS_IS_OK(status)) {
5089		return status;
5090	}
5091
5092	if (ret != (SMB_OFF_T)src_sbuf.st_size) {
5093		return NT_STATUS_DISK_FULL;
5094	}
5095
5096	return NT_STATUS_OK;
5097}
5098
5099/****************************************************************************
5100 Reply to a file copy.
5101****************************************************************************/
5102
5103int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5104{
5105	int outsize = 0;
5106	pstring name;
5107	pstring directory;
5108	pstring mask,newname;
5109	char *p;
5110	int count=0;
5111	int error = ERRnoaccess;
5112	int err = 0;
5113	int tid2 = SVAL(inbuf,smb_vwv0);
5114	int ofun = SVAL(inbuf,smb_vwv1);
5115	int flags = SVAL(inbuf,smb_vwv2);
5116	BOOL target_is_directory=False;
5117	BOOL source_has_wild = False;
5118	BOOL dest_has_wild = False;
5119	SMB_STRUCT_STAT sbuf1, sbuf2;
5120	NTSTATUS status;
5121	START_PROFILE(SMBcopy);
5122
5123	*directory = *mask = 0;
5124
5125	p = smb_buf(inbuf);
5126	p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &source_has_wild);
5127	if (!NT_STATUS_IS_OK(status)) {
5128		END_PROFILE(SMBcopy);
5129		return ERROR_NT(status);
5130	}
5131	p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wild);
5132	if (!NT_STATUS_IS_OK(status)) {
5133		END_PROFILE(SMBcopy);
5134		return ERROR_NT(status);
5135	}
5136
5137	DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
5138
5139	if (tid2 != conn->cnum) {
5140		/* can't currently handle inter share copies XXXX */
5141		DEBUG(3,("Rejecting inter-share copy\n"));
5142		END_PROFILE(SMBcopy);
5143		return ERROR_DOS(ERRSRV,ERRinvdevice);
5144	}
5145
5146	status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, name, &source_has_wild);
5147	if (!NT_STATUS_IS_OK(status)) {
5148		END_PROFILE(SMBcopy);
5149		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5150			return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5151		}
5152		return ERROR_NT(status);
5153	}
5154
5155	status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wild);
5156	if (!NT_STATUS_IS_OK(status)) {
5157		END_PROFILE(SMBcopy);
5158		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5159			return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5160		}
5161		return ERROR_NT(status);
5162	}
5163
5164	status = unix_convert(conn, name, source_has_wild, NULL, &sbuf1);
5165	if (!NT_STATUS_IS_OK(status)) {
5166		END_PROFILE(SMBcopy);
5167		return ERROR_NT(status);
5168	}
5169
5170	status = unix_convert(conn, newname, dest_has_wild, NULL, &sbuf2);
5171	if (!NT_STATUS_IS_OK(status)) {
5172		END_PROFILE(SMBcopy);
5173		return ERROR_NT(status);
5174	}
5175
5176	target_is_directory = VALID_STAT_OF_DIR(sbuf2);
5177
5178	if ((flags&1) && target_is_directory) {
5179		END_PROFILE(SMBcopy);
5180		return ERROR_DOS(ERRDOS,ERRbadfile);
5181	}
5182
5183	if ((flags&2) && !target_is_directory) {
5184		END_PROFILE(SMBcopy);
5185		return ERROR_DOS(ERRDOS,ERRbadpath);
5186	}
5187
5188	if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
5189		/* wants a tree copy! XXXX */
5190		DEBUG(3,("Rejecting tree copy\n"));
5191		END_PROFILE(SMBcopy);
5192		return ERROR_DOS(ERRSRV,ERRerror);
5193	}
5194
5195	p = strrchr_m(name,'/');
5196	if (!p) {
5197		pstrcpy(directory,"./");
5198		pstrcpy(mask,name);
5199	} else {
5200		*p = 0;
5201		pstrcpy(directory,name);
5202		pstrcpy(mask,p+1);
5203	}
5204
5205	/*
5206	 * We should only check the mangled cache
5207	 * here if unix_convert failed. This means
5208	 * that the path in 'mask' doesn't exist
5209	 * on the file system and so we need to look
5210	 * for a possible mangle. This patch from
5211	 * Tine Smukavec <valentin.smukavec@hermes.si>.
5212	 */
5213
5214	if (!VALID_STAT(sbuf1) && mangle_is_mangled(mask, conn->params)) {
5215		mangle_check_cache( mask, sizeof(pstring)-1, conn->params );
5216	}
5217
5218	if (!source_has_wild) {
5219		pstrcat(directory,"/");
5220		pstrcat(directory,mask);
5221		if (dest_has_wild) {
5222			if (!resolve_wildcards(directory,newname)) {
5223				END_PROFILE(SMBcopy);
5224				return ERROR_NT(NT_STATUS_NO_MEMORY);
5225			}
5226		}
5227
5228		status = check_name(conn, directory);
5229		if (!NT_STATUS_IS_OK(status)) {
5230			return ERROR_NT(status);
5231		}
5232
5233		status = check_name(conn, newname);
5234		if (!NT_STATUS_IS_OK(status)) {
5235			return ERROR_NT(status);
5236		}
5237
5238		status = copy_file(conn,directory,newname,ofun,
5239					count,target_is_directory);
5240
5241		if(!NT_STATUS_IS_OK(status)) {
5242			END_PROFILE(SMBcopy);
5243			return ERROR_NT(status);
5244		} else {
5245			count++;
5246		}
5247	} else {
5248		struct smb_Dir *dir_hnd = NULL;
5249		const char *dname;
5250		long offset = 0;
5251		pstring destname;
5252
5253		if (strequal(mask,"????????.???"))
5254			pstrcpy(mask,"*");
5255
5256		status = check_name(conn, directory);
5257		if (!NT_STATUS_IS_OK(status)) {
5258			return ERROR_NT(status);
5259		}
5260
5261		dir_hnd = OpenDir(conn, directory, mask, 0);
5262		if (dir_hnd == NULL) {
5263			status = map_nt_error_from_unix(errno);
5264			return ERROR_NT(status);
5265		}
5266
5267		error = ERRbadfile;
5268
5269		while ((dname = ReadDirName(dir_hnd, &offset))) {
5270			pstring fname;
5271			pstrcpy(fname,dname);
5272
5273			if (!is_visible_file(conn, directory, dname, &sbuf1, False)) {
5274				continue;
5275			}
5276
5277			if(!mask_match(fname, mask, conn->case_sensitive)) {
5278				continue;
5279			}
5280
5281			error = ERRnoaccess;
5282			slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
5283			pstrcpy(destname,newname);
5284			if (!resolve_wildcards(fname,destname)) {
5285				continue;
5286			}
5287
5288			status = check_name(conn, fname);
5289			if (!NT_STATUS_IS_OK(status)) {
5290				return ERROR_NT(status);
5291			}
5292
5293			status = check_name(conn, destname);
5294			if (!NT_STATUS_IS_OK(status)) {
5295				return ERROR_NT(status);
5296			}
5297
5298			DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname, destname));
5299
5300			status = copy_file(conn,fname,destname,ofun,
5301					count,target_is_directory);
5302			if (NT_STATUS_IS_OK(status)) {
5303				count++;
5304			}
5305		}
5306		CloseDir(dir_hnd);
5307	}
5308
5309	if (count == 0) {
5310		if(err) {
5311			/* Error on close... */
5312			errno = err;
5313			END_PROFILE(SMBcopy);
5314			return(UNIXERROR(ERRHRD,ERRgeneral));
5315		}
5316
5317		END_PROFILE(SMBcopy);
5318		return ERROR_DOS(ERRDOS,error);
5319	}
5320
5321	outsize = set_message(outbuf,1,0,True);
5322	SSVAL(outbuf,smb_vwv0,count);
5323
5324	END_PROFILE(SMBcopy);
5325	return(outsize);
5326}
5327
5328/****************************************************************************
5329 Reply to a setdir.
5330****************************************************************************/
5331
5332int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
5333{
5334	int snum;
5335	int outsize = 0;
5336	pstring newdir;
5337	NTSTATUS status;
5338
5339	START_PROFILE(pathworks_setdir);
5340
5341	snum = SNUM(conn);
5342	if (!CAN_SETDIR(snum)) {
5343		END_PROFILE(pathworks_setdir);
5344		return ERROR_DOS(ERRDOS,ERRnoaccess);
5345	}
5346
5347	srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status);
5348	if (!NT_STATUS_IS_OK(status)) {
5349		END_PROFILE(pathworks_setdir);
5350		return ERROR_NT(status);
5351	}
5352
5353	status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newdir);
5354	if (!NT_STATUS_IS_OK(status)) {
5355		END_PROFILE(pathworks_setdir);
5356		if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5357			return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5358		}
5359		return ERROR_NT(status);
5360	}
5361
5362	if (strlen(newdir) != 0) {
5363		if (!vfs_directory_exist(conn,newdir,NULL)) {
5364			END_PROFILE(pathworks_setdir);
5365			return ERROR_DOS(ERRDOS,ERRbadpath);
5366		}
5367		set_conn_connectpath(conn,newdir);
5368	}
5369
5370	outsize = set_message(outbuf,0,0,False);
5371	SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
5372
5373	DEBUG(3,("setdir %s\n", newdir));
5374
5375	END_PROFILE(pathworks_setdir);
5376	return(outsize);
5377}
5378
5379#undef DBGC_CLASS
5380#define DBGC_CLASS DBGC_LOCKING
5381
5382/****************************************************************************
5383 Get a lock pid, dealing with large count requests.
5384****************************************************************************/
5385
5386uint32 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
5387{
5388	if(!large_file_format)
5389		return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
5390	else
5391		return (uint32)SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
5392}
5393
5394/****************************************************************************
5395 Get a lock count, dealing with large count requests.
5396****************************************************************************/
5397
5398SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
5399{
5400	SMB_BIG_UINT count = 0;
5401
5402	if(!large_file_format) {
5403		count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
5404	} else {
5405
5406#if defined(HAVE_LONGLONG)
5407		count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
5408			((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
5409#else /* HAVE_LONGLONG */
5410
5411		/*
5412		 * NT4.x seems to be broken in that it sends large file (64 bit)
5413		 * lockingX calls even if the CAP_LARGE_FILES was *not*
5414		 * negotiated. For boxes without large unsigned ints truncate the
5415		 * lock count by dropping the top 32 bits.
5416		 */
5417
5418		if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
5419			DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
5420				(unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
5421				(unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
5422				SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
5423		}
5424
5425		count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
5426#endif /* HAVE_LONGLONG */
5427	}
5428
5429	return count;
5430}
5431
5432#if !defined(HAVE_LONGLONG)
5433/****************************************************************************
5434 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
5435****************************************************************************/
5436
5437static uint32 map_lock_offset(uint32 high, uint32 low)
5438{
5439	unsigned int i;
5440	uint32 mask = 0;
5441	uint32 highcopy = high;
5442
5443	/*
5444	 * Try and find out how many significant bits there are in high.
5445	 */
5446
5447	for(i = 0; highcopy; i++)
5448		highcopy >>= 1;
5449
5450	/*
5451	 * We use 31 bits not 32 here as POSIX
5452	 * lock offsets may not be negative.
5453	 */
5454
5455	mask = (~0) << (31 - i);
5456
5457	if(low & mask)
5458		return 0; /* Fail. */
5459
5460	high <<= (31 - i);
5461
5462	return (high|low);
5463}
5464#endif /* !defined(HAVE_LONGLONG) */
5465
5466/****************************************************************************
5467 Get a lock offset, dealing with large offset requests.
5468****************************************************************************/
5469
5470SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
5471{
5472	SMB_BIG_UINT offset = 0;
5473
5474	*err = False;
5475
5476	if(!large_file_format) {
5477		offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
5478	} else {
5479
5480#if defined(HAVE_LONGLONG)
5481		offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
5482				((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
5483#else /* HAVE_LONGLONG */
5484
5485		/*
5486		 * NT4.x seems to be broken in that it sends large file (64 bit)
5487		 * lockingX calls even if the CAP_LARGE_FILES was *not*
5488		 * negotiated. For boxes without large unsigned ints mangle the
5489		 * lock offset by mapping the top 32 bits onto the lower 32.
5490		 */
5491
5492		if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
5493			uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5494			uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
5495			uint32 new_low = 0;
5496
5497			if((new_low = map_lock_offset(high, low)) == 0) {
5498				*err = True;
5499				return (SMB_BIG_UINT)-1;
5500			}
5501
5502			DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
5503				(unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
5504			SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
5505			SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
5506		}
5507
5508		offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
5509#endif /* HAVE_LONGLONG */
5510	}
5511
5512	return offset;
5513}
5514
5515/****************************************************************************
5516 Reply to a lockingX request.
5517****************************************************************************/
5518
5519int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
5520		   int length, int bufsize)
5521{
5522	files_struct *fsp = file_fsp(inbuf,smb_vwv2);
5523	unsigned char locktype = CVAL(inbuf,smb_vwv3);
5524	unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
5525	uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
5526	uint16 num_locks = SVAL(inbuf,smb_vwv7);
5527	SMB_BIG_UINT count = 0, offset = 0;
5528	uint32 lock_pid;
5529	int32 lock_timeout = IVAL(inbuf,smb_vwv4);
5530	int i;
5531	char *data;
5532	BOOL large_file_format =
5533		(locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
5534	BOOL err;
5535	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
5536
5537	START_PROFILE(SMBlockingX);
5538
5539	CHECK_FSP(fsp,conn);
5540
5541	data = smb_buf(inbuf);
5542
5543	if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
5544		/* we don't support these - and CANCEL_LOCK makes w2k
5545		   and XP reboot so I don't really want to be
5546		   compatible! (tridge) */
5547		return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
5548	}
5549
5550	/* Check if this is an oplock break on a file
5551	   we have granted an oplock on.
5552	*/
5553	if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
5554		/* Client can insist on breaking to none. */
5555		BOOL break_to_none = (oplocklevel == 0);
5556		BOOL result;
5557
5558		DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
5559			 "for fnum = %d\n", (unsigned int)oplocklevel,
5560			 fsp->fnum ));
5561
5562		/*
5563		 * Make sure we have granted an exclusive or batch oplock on
5564		 * this file.
5565		 */
5566
5567		if (fsp->oplock_type == 0) {
5568
5569			/* The Samba4 nbench simulator doesn't understand
5570			   the difference between break to level2 and break
5571			   to none from level2 - it sends oplock break
5572			   replies in both cases. Don't keep logging an error
5573			   message here - just ignore it. JRA. */
5574
5575			DEBUG(5,("reply_lockingX: Error : oplock break from "
5576				 "client for fnum = %d (oplock=%d) and no "
5577				 "oplock granted on this file (%s).\n",
5578				 fsp->fnum, fsp->oplock_type, fsp->fsp_name));
5579
5580			/* if this is a pure oplock break request then don't
5581			 * send a reply */
5582			if (num_locks == 0 && num_ulocks == 0) {
5583				END_PROFILE(SMBlockingX);
5584				return -1;
5585			} else {
5586				END_PROFILE(SMBlockingX);
5587				return ERROR_DOS(ERRDOS,ERRlock);
5588			}
5589		}
5590
5591		if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
5592		    (break_to_none)) {
5593			result = remove_oplock(fsp);
5594		} else {
5595			result = downgrade_oplock(fsp);
5596		}
5597
5598		if (!result) {
5599			DEBUG(0, ("reply_lockingX: error in removing "
5600				  "oplock on file %s\n", fsp->fsp_name));
5601			/* Hmmm. Is this panic justified? */
5602			smb_panic("internal tdb error");
5603		}
5604
5605		reply_to_oplock_break_requests(fsp);
5606
5607		/* if this is a pure oplock break request then don't send a
5608		 * reply */
5609		if (num_locks == 0 && num_ulocks == 0) {
5610			/* Sanity check - ensure a pure oplock break is not a
5611			   chained request. */
5612			if(CVAL(inbuf,smb_vwv0) != 0xff)
5613				DEBUG(0,("reply_lockingX: Error : pure oplock "
5614					 "break is a chained %d request !\n",
5615					 (unsigned int)CVAL(inbuf,smb_vwv0) ));
5616			END_PROFILE(SMBlockingX);
5617			return -1;
5618		}
5619	}
5620
5621	/*
5622	 * We do this check *after* we have checked this is not a oplock break
5623	 * response message. JRA.
5624	 */
5625
5626	release_level_2_oplocks_on_change(fsp);
5627
5628	/* Data now points at the beginning of the list
5629	   of smb_unlkrng structs */
5630	for(i = 0; i < (int)num_ulocks; i++) {
5631		lock_pid = get_lock_pid( data, i, large_file_format);
5632		count = get_lock_count( data, i, large_file_format);
5633		offset = get_lock_offset( data, i, large_file_format, &err);
5634
5635		/*
5636		 * There is no error code marked "stupid client bug".... :-).
5637		 */
5638		if(err) {
5639			END_PROFILE(SMBlockingX);
5640			return ERROR_DOS(ERRDOS,ERRnoaccess);
5641		}
5642
5643		DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
5644			  "pid %u, file %s\n", (double)offset, (double)count,
5645			  (unsigned int)lock_pid, fsp->fsp_name ));
5646
5647		status = do_unlock(fsp,
5648				lock_pid,
5649				count,
5650				offset,
5651				WINDOWS_LOCK);
5652
5653		if (NT_STATUS_V(status)) {
5654			END_PROFILE(SMBlockingX);
5655			return ERROR_NT(status);
5656		}
5657	}
5658
5659	/* Setup the timeout in seconds. */
5660
5661	if (!lp_blocking_locks(SNUM(conn))) {
5662		lock_timeout = 0;
5663	}
5664
5665	/* Now do any requested locks */
5666	data += ((large_file_format ? 20 : 10)*num_ulocks);
5667
5668	/* Data now points at the beginning of the list
5669	   of smb_lkrng structs */
5670
5671	for(i = 0; i < (int)num_locks; i++) {
5672		enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
5673				READ_LOCK:WRITE_LOCK);
5674		lock_pid = get_lock_pid( data, i, large_file_format);
5675		count = get_lock_count( data, i, large_file_format);
5676		offset = get_lock_offset( data, i, large_file_format, &err);
5677
5678		/*
5679		 * There is no error code marked "stupid client bug".... :-).
5680		 */
5681		if(err) {
5682			END_PROFILE(SMBlockingX);
5683			return ERROR_DOS(ERRDOS,ERRnoaccess);
5684		}
5685
5686		DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
5687			  "%u, file %s timeout = %d\n", (double)offset,
5688			  (double)count, (unsigned int)lock_pid,
5689			  fsp->fsp_name, (int)lock_timeout ));
5690
5691		if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
5692			if (lp_blocking_locks(SNUM(conn))) {
5693
5694				/* Schedule a message to ourselves to
5695				   remove the blocking lock record and
5696				   return the right error. */
5697
5698				if (!blocking_lock_cancel(fsp,
5699						lock_pid,
5700						offset,
5701						count,
5702						WINDOWS_LOCK,
5703						locktype,
5704						NT_STATUS_FILE_LOCK_CONFLICT)) {
5705					END_PROFILE(SMBlockingX);
5706					return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
5707				}
5708			}
5709			/* Remove a matching pending lock. */
5710			status = do_lock_cancel(fsp,
5711						lock_pid,
5712						count,
5713						offset,
5714						WINDOWS_LOCK);
5715		} else {
5716			BOOL blocking_lock = lock_timeout ? True : False;
5717			BOOL defer_lock = False;
5718			struct byte_range_lock *br_lck;
5719			uint32 block_smbpid;
5720
5721			br_lck = do_lock(fsp,
5722					lock_pid,
5723					count,
5724					offset,
5725					lock_type,
5726					WINDOWS_LOCK,
5727					blocking_lock,
5728					&status,
5729					&block_smbpid);
5730
5731			if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5732				/* Windows internal resolution for blocking locks seems
5733				   to be about 200ms... Don't wait for less than that. JRA. */
5734				if (lock_timeout != -1 && lock_timeout < lp_lock_spin_time()) {
5735					lock_timeout = lp_lock_spin_time();
5736				}
5737				defer_lock = True;
5738			}
5739
5740			/* This heuristic seems to match W2K3 very well. If a
5741			   lock sent with timeout of zero would fail with NT_STATUS_FILE_LOCK_CONFLICT
5742			   it pretends we asked for a timeout of between 150 - 300 milliseconds as
5743			   far as I can tell. Replacement for do_lock_spin(). JRA. */
5744
5745			if (br_lck && lp_blocking_locks(SNUM(conn)) && !blocking_lock &&
5746					NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT)) {
5747				defer_lock = True;
5748				lock_timeout = lp_lock_spin_time();
5749			}
5750
5751			if (br_lck && defer_lock) {
5752				/*
5753				 * A blocking lock was requested. Package up
5754				 * this smb into a queued request and push it
5755				 * onto the blocking lock queue.
5756				 */
5757				if(push_blocking_lock_request(br_lck,
5758							inbuf, length,
5759							fsp,
5760							lock_timeout,
5761							i,
5762							lock_pid,
5763							lock_type,
5764							WINDOWS_LOCK,
5765							offset,
5766							count,
5767							block_smbpid)) {
5768					TALLOC_FREE(br_lck);
5769					END_PROFILE(SMBlockingX);
5770					return -1;
5771				}
5772			}
5773
5774			TALLOC_FREE(br_lck);
5775		}
5776
5777		if (NT_STATUS_V(status)) {
5778			END_PROFILE(SMBlockingX);
5779			return ERROR_NT(status);
5780		}
5781	}
5782
5783	/* If any of the above locks failed, then we must unlock
5784	   all of the previous locks (X/Open spec). */
5785
5786	if (!(locktype & LOCKING_ANDX_CANCEL_LOCK) &&
5787			(i != num_locks) &&
5788			(num_locks != 0)) {
5789		/*
5790		 * Ensure we don't do a remove on the lock that just failed,
5791		 * as under POSIX rules, if we have a lock already there, we
5792		 * will delete it (and we shouldn't) .....
5793		 */
5794		for(i--; i >= 0; i--) {
5795			lock_pid = get_lock_pid( data, i, large_file_format);
5796			count = get_lock_count( data, i, large_file_format);
5797			offset = get_lock_offset( data, i, large_file_format,
5798						  &err);
5799
5800			/*
5801			 * There is no error code marked "stupid client
5802			 * bug".... :-).
5803			 */
5804			if(err) {
5805				END_PROFILE(SMBlockingX);
5806				return ERROR_DOS(ERRDOS,ERRnoaccess);
5807			}
5808
5809			do_unlock(fsp,
5810				lock_pid,
5811				count,
5812				offset,
5813				WINDOWS_LOCK);
5814		}
5815		END_PROFILE(SMBlockingX);
5816		return ERROR_NT(status);
5817	}
5818
5819	set_message(outbuf,2,0,True);
5820
5821	DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
5822		  fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
5823
5824	END_PROFILE(SMBlockingX);
5825	return chain_reply(inbuf,outbuf,length,bufsize);
5826}
5827
5828#undef DBGC_CLASS
5829#define DBGC_CLASS DBGC_ALL
5830
5831/****************************************************************************
5832 Reply to a SMBreadbmpx (read block multiplex) request.
5833****************************************************************************/
5834
5835int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
5836{
5837	ssize_t nread = -1;
5838	ssize_t total_read;
5839	char *data;
5840	SMB_OFF_T startpos;
5841	int outsize;
5842	size_t maxcount;
5843	int max_per_packet;
5844	size_t tcount;
5845	int pad;
5846	files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5847	START_PROFILE(SMBreadBmpx);
5848
5849	/* this function doesn't seem to work - disable by default */
5850	if (!lp_readbmpx()) {
5851		END_PROFILE(SMBreadBmpx);
5852		return ERROR_DOS(ERRSRV,ERRuseSTD);
5853	}
5854
5855	outsize = set_message(outbuf,8,0,True);
5856
5857	CHECK_FSP(fsp,conn);
5858	if (!CHECK_READ(fsp,inbuf)) {
5859		return(ERROR_DOS(ERRDOS,ERRbadaccess));
5860	}
5861
5862	startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
5863	maxcount = SVAL(inbuf,smb_vwv3);
5864
5865	data = smb_buf(outbuf);
5866	pad = ((long)data)%4;
5867	if (pad)
5868		pad = 4 - pad;
5869	data += pad;
5870
5871	max_per_packet = bufsize-(outsize+pad);
5872	tcount = maxcount;
5873	total_read = 0;
5874
5875	if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
5876		END_PROFILE(SMBreadBmpx);
5877		return ERROR_DOS(ERRDOS,ERRlock);
5878	}
5879
5880	do {
5881		size_t N = MIN(max_per_packet,tcount-total_read);
5882
5883		nread = read_file(fsp,data,startpos,N);
5884
5885		if (nread <= 0)
5886			nread = 0;
5887
5888		if (nread < (ssize_t)N)
5889			tcount = total_read + nread;
5890
5891		set_message(outbuf,8,nread+pad,False);
5892		SIVAL(outbuf,smb_vwv0,startpos);
5893		SSVAL(outbuf,smb_vwv2,tcount);
5894		SSVAL(outbuf,smb_vwv6,nread);
5895		SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
5896
5897		show_msg(outbuf);
5898		if (!send_smb(smbd_server_fd(),outbuf))
5899			exit_server_cleanly("reply_readbmpx: send_smb failed.");
5900
5901		total_read += nread;
5902		startpos += nread;
5903	} while (total_read < (ssize_t)tcount);
5904
5905	END_PROFILE(SMBreadBmpx);
5906	return(-1);
5907}
5908
5909/****************************************************************************
5910 Reply to a SMBsetattrE.
5911****************************************************************************/
5912
5913int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5914{
5915	struct timespec ts[2];
5916	int outsize = 0;
5917	files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5918	START_PROFILE(SMBsetattrE);
5919
5920	outsize = set_message(outbuf,0,0,False);
5921
5922	if(!fsp || (fsp->conn != conn)) {
5923		END_PROFILE(SMBsetattrE);
5924		return ERROR_DOS(ERRDOS,ERRbadfid);
5925	}
5926
5927	/*
5928	 * Convert the DOS times into unix times. Ignore create
5929	 * time as UNIX can't set this.
5930	 */
5931
5932	ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv3)); /* atime. */
5933	ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(inbuf+smb_vwv5)); /* mtime. */
5934
5935	/*
5936	 * Patch from Ray Frush <frush@engr.colostate.edu>
5937	 * Sometimes times are sent as zero - ignore them.
5938	 */
5939
5940	if (null_timespec(ts[0]) && null_timespec(ts[1])) {
5941		/* Ignore request */
5942		if( DEBUGLVL( 3 ) ) {
5943			dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
5944			dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
5945		}
5946		END_PROFILE(SMBsetattrE);
5947		return(outsize);
5948	} else if (!null_timespec(ts[0]) && null_timespec(ts[1])) {
5949		/* set modify time = to access time if modify time was unset */
5950		ts[1] = ts[0];
5951	}
5952
5953	/* Set the date on this file */
5954	/* Should we set pending modtime here ? JRA */
5955	if(file_ntimes(conn, fsp->fsp_name, ts)) {
5956		END_PROFILE(SMBsetattrE);
5957		return ERROR_DOS(ERRDOS,ERRnoaccess);
5958	}
5959
5960	DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
5961		fsp->fnum,
5962		(unsigned int)ts[0].tv_sec,
5963		(unsigned int)ts[1].tv_sec));
5964
5965	END_PROFILE(SMBsetattrE);
5966	return(outsize);
5967}
5968
5969
5970/* Back from the dead for OS/2..... JRA. */
5971
5972/****************************************************************************
5973 Reply to a SMBwritebmpx (write block multiplex primary) request.
5974****************************************************************************/
5975
5976int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
5977{
5978	size_t numtowrite;
5979	ssize_t nwritten = -1;
5980	int outsize = 0;
5981	SMB_OFF_T startpos;
5982	size_t tcount;
5983	BOOL write_through;
5984	int smb_doff;
5985	char *data;
5986	files_struct *fsp = file_fsp(inbuf,smb_vwv0);
5987	NTSTATUS status;
5988	START_PROFILE(SMBwriteBmpx);
5989
5990	CHECK_FSP(fsp,conn);
5991	if (!CHECK_WRITE(fsp)) {
5992		return(ERROR_DOS(ERRDOS,ERRbadaccess));
5993	}
5994	if (HAS_CACHED_ERROR(fsp)) {
5995		return(CACHED_ERROR(fsp));
5996	}
5997
5998	tcount = SVAL(inbuf,smb_vwv1);
5999	startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
6000	write_through = BITSETW(inbuf+smb_vwv7,0);
6001	numtowrite = SVAL(inbuf,smb_vwv10);
6002	smb_doff = SVAL(inbuf,smb_vwv11);
6003
6004	data = smb_base(inbuf) + smb_doff;
6005
6006	/* If this fails we need to send an SMBwriteC response,
6007		not an SMBwritebmpx - set this up now so we don't forget */
6008	SCVAL(outbuf,smb_com,SMBwritec);
6009
6010	if (is_locked(fsp,(uint32)SVAL(inbuf,smb_pid),(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
6011		END_PROFILE(SMBwriteBmpx);
6012		return(ERROR_DOS(ERRDOS,ERRlock));
6013	}
6014
6015	nwritten = write_file(fsp,data,startpos,numtowrite);
6016
6017	status = sync_file(conn, fsp, write_through);
6018	if (!NT_STATUS_IS_OK(status)) {
6019		END_PROFILE(SMBwriteBmpx);
6020		DEBUG(5,("reply_writebmpx: sync_file for %s returned %s\n",
6021			fsp->fsp_name, nt_errstr(status) ));
6022		return ERROR_NT(status);
6023	}
6024
6025	if(nwritten < (ssize_t)numtowrite) {
6026		END_PROFILE(SMBwriteBmpx);
6027		return(UNIXERROR(ERRHRD,ERRdiskfull));
6028	}
6029
6030	/* If the maximum to be written to this file
6031		is greater than what we just wrote then set
6032		up a secondary struct to be attached to this
6033		fd, we will use this to cache error messages etc. */
6034
6035	if((ssize_t)tcount > nwritten) {
6036		write_bmpx_struct *wbms;
6037		if(fsp->wbmpx_ptr != NULL)
6038			wbms = fsp->wbmpx_ptr; /* Use an existing struct */
6039		else
6040			wbms = SMB_MALLOC_P(write_bmpx_struct);
6041		if(!wbms) {
6042			DEBUG(0,("Out of memory in reply_readmpx\n"));
6043			END_PROFILE(SMBwriteBmpx);
6044			return(ERROR_DOS(ERRSRV,ERRnoresource));
6045		}
6046		wbms->wr_mode = write_through;
6047		wbms->wr_discard = False; /* No errors yet */
6048		wbms->wr_total_written = nwritten;
6049		wbms->wr_errclass = 0;
6050		wbms->wr_error = 0;
6051		fsp->wbmpx_ptr = wbms;
6052	}
6053
6054	/* We are returning successfully, set the message type back to
6055		SMBwritebmpx */
6056	SCVAL(outbuf,smb_com,SMBwriteBmpx);
6057
6058	outsize = set_message(outbuf,1,0,True);
6059
6060	SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
6061
6062	DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
6063			fsp->fnum, (int)numtowrite, (int)nwritten ) );
6064
6065	if (write_through && tcount==nwritten) {
6066		/* We need to send both a primary and a secondary response */
6067		smb_setlen(outbuf,outsize - 4);
6068		show_msg(outbuf);
6069		if (!send_smb(smbd_server_fd(),outbuf))
6070			exit_server_cleanly("reply_writebmpx: send_smb failed.");
6071
6072		/* Now the secondary */
6073		outsize = set_message(outbuf,1,0,True);
6074		SCVAL(outbuf,smb_com,SMBwritec);
6075		SSVAL(outbuf,smb_vwv0,nwritten);
6076	}
6077
6078	END_PROFILE(SMBwriteBmpx);
6079	return(outsize);
6080}
6081
6082/****************************************************************************
6083 Reply to a SMBwritebs (write block multiplex secondary) request.
6084****************************************************************************/
6085
6086int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
6087{
6088	size_t numtowrite;
6089	ssize_t nwritten = -1;
6090	int outsize = 0;
6091	SMB_OFF_T startpos;
6092	size_t tcount;
6093	BOOL write_through;
6094	int smb_doff;
6095	char *data;
6096	write_bmpx_struct *wbms;
6097	BOOL send_response = False;
6098	files_struct *fsp = file_fsp(inbuf,smb_vwv0);
6099	NTSTATUS status;
6100	START_PROFILE(SMBwriteBs);
6101
6102	CHECK_FSP(fsp,conn);
6103	if (!CHECK_WRITE(fsp)) {
6104		return(ERROR_DOS(ERRDOS,ERRbadaccess));
6105	}
6106
6107	tcount = SVAL(inbuf,smb_vwv1);
6108	startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
6109	numtowrite = SVAL(inbuf,smb_vwv6);
6110	smb_doff = SVAL(inbuf,smb_vwv7);
6111
6112	data = smb_base(inbuf) + smb_doff;
6113
6114	/* We need to send an SMBwriteC response, not an SMBwritebs */
6115	SCVAL(outbuf,smb_com,SMBwritec);
6116
6117	/* This fd should have an auxiliary struct attached,
6118		check that it does */
6119	wbms = fsp->wbmpx_ptr;
6120	if(!wbms) {
6121		END_PROFILE(SMBwriteBs);
6122		return(-1);
6123	}
6124
6125	/* If write through is set we can return errors, else we must cache them */
6126	write_through = wbms->wr_mode;
6127
6128	/* Check for an earlier error */
6129	if(wbms->wr_discard) {
6130		END_PROFILE(SMBwriteBs);
6131		return -1; /* Just discard the packet */
6132	}
6133
6134	nwritten = write_file(fsp,data,startpos,numtowrite);
6135
6136	status = sync_file(conn, fsp, write_through);
6137
6138	if (nwritten < (ssize_t)numtowrite || !NT_STATUS_IS_OK(status)) {
6139		if(write_through) {
6140			/* We are returning an error - we can delete the aux struct */
6141			if (wbms)
6142				free((char *)wbms);
6143			fsp->wbmpx_ptr = NULL;
6144			END_PROFILE(SMBwriteBs);
6145			return(ERROR_DOS(ERRHRD,ERRdiskfull));
6146		}
6147		wbms->wr_errclass = ERRHRD;
6148		wbms->wr_error = ERRdiskfull;
6149		wbms->wr_status = NT_STATUS_DISK_FULL;
6150		wbms->wr_discard = True;
6151		END_PROFILE(SMBwriteBs);
6152		return -1;
6153	}
6154
6155	/* Increment the total written, if this matches tcount
6156		we can discard the auxiliary struct (hurrah !) and return a writeC */
6157	wbms->wr_total_written += nwritten;
6158	if(wbms->wr_total_written >= tcount) {
6159		if (write_through) {
6160			outsize = set_message(outbuf,1,0,True);
6161			SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
6162			send_response = True;
6163		}
6164
6165		free((char *)wbms);
6166		fsp->wbmpx_ptr = NULL;
6167	}
6168
6169	if(send_response) {
6170		END_PROFILE(SMBwriteBs);
6171		return(outsize);
6172	}
6173
6174	END_PROFILE(SMBwriteBs);
6175	return(-1);
6176}
6177
6178/****************************************************************************
6179 Reply to a SMBgetattrE.
6180****************************************************************************/
6181
6182int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
6183{
6184	SMB_STRUCT_STAT sbuf;
6185	int outsize = 0;
6186	int mode;
6187	files_struct *fsp = file_fsp(inbuf,smb_vwv0);
6188	START_PROFILE(SMBgetattrE);
6189
6190	outsize = set_message(outbuf,11,0,True);
6191
6192	if(!fsp || (fsp->conn != conn)) {
6193		END_PROFILE(SMBgetattrE);
6194		return ERROR_DOS(ERRDOS,ERRbadfid);
6195	}
6196
6197	/* Do an fstat on this file */
6198	if(fsp_stat(fsp, &sbuf)) {
6199		END_PROFILE(SMBgetattrE);
6200		return(UNIXERROR(ERRDOS,ERRnoaccess));
6201	}
6202
6203	mode = dos_mode(conn,fsp->fsp_name,&sbuf);
6204
6205	/*
6206	 * Convert the times into dos times. Set create
6207	 * date to be last modify date as UNIX doesn't save
6208	 * this.
6209	 */
6210
6211	srv_put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
6212	srv_put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
6213	/* Should we check pending modtime here ? JRA */
6214	srv_put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
6215
6216	if (mode & aDIR) {
6217		SIVAL(outbuf,smb_vwv6,0);
6218		SIVAL(outbuf,smb_vwv8,0);
6219	} else {
6220		uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
6221		SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
6222		SIVAL(outbuf,smb_vwv8,allocation_size);
6223	}
6224	SSVAL(outbuf,smb_vwv10, mode);
6225
6226	DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
6227
6228	END_PROFILE(SMBgetattrE);
6229	return(outsize);
6230}
6231