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