1/*
2   Unix SMB/CIFS implementation.
3   SMB transaction2 handling
4   Copyright (C) Jeremy Allison			1994-2003
5   Copyright (C) Stefan (metze) Metzmacher	2003
6
7   Extensively modified by Andrew Tridgell, 1995
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; either version 2 of the License, or
12   (at your option) any later version.
13
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22*/
23
24#include "includes.h"
25
26extern enum protocol_types Protocol;
27extern int smb_read_error;
28extern int global_oplock_break;
29extern uint32 global_client_caps;
30extern struct current_user current_user;
31
32/* Foxconn modified start pling 11/25/2009 */
33//#define get_file_size(sbuf) ((sbuf).st_size)
34#define get_file_size(sbuf)  get_file_size2(sbuf)
35static SMB_BIG_UINT get_file_size2(struct stat st)
36{
37    SMB_BIG_UINT file_size_64;
38    SMB_BIG_UINT order;
39
40    /* Check whether file size > 4GB which exceeds 32-bit st->st_size
41     *  st->sb_blocks in units of 512 bytes.
42     *  If 'st->sb_blocks' x 512 > 4GB, then this file > 4GB.
43     */
44    if (st.st_blocks >= 8388608L)
45    {
46        order = st.st_blocks / 8388608L;  // order = # of 4GB
47        file_size_64 = 0x100000000 * order + (unsigned long)(st.st_size);
48    }
49    else
50        file_size_64 = st.st_size & 0xFFFFFFFF;
51
52    return file_size_64;
53}
54/* Foxconn modified end pling 11/25/2009 */
55
56#define DIR_ENTRY_SAFETY_MARGIN 4096
57
58/********************************************************************
59 Roundup a value to the nearest allocation roundup size boundary.
60 Only do this for Windows clients.
61********************************************************************/
62
63SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
64{
65	SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
66
67	/* Only roundup for Windows clients. */
68	enum remote_arch_types ra_type = get_remote_arch();
69	if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
70		val = SMB_ROUNDUP(val,rval);
71	}
72	return val;
73}
74
75/********************************************************************
76 Given a stat buffer return the allocated size on disk, taking into
77 account sparse files.
78********************************************************************/
79
80SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
81{
82	SMB_BIG_UINT ret;
83
84#if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
85	ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
86#else
87    /* Foxconn modified start pling 11/25/2009 */
88    /* Set the correct allocation size, even for large files */
89	//ret = (SMB_BIG_UINT)get_file_size(*sbuf);
90	ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
91    /* Foxconn modified start pling 11/25/2009 */
92#endif
93
94	if (!ret && fsp && fsp->initial_allocation_size)
95		ret = fsp->initial_allocation_size;
96
97	return smb_roundup(conn, ret);
98}
99
100/****************************************************************************
101 Utility functions for dealing with extended attributes.
102****************************************************************************/
103
104static const char *prohibited_ea_names[] = {
105	SAMBA_POSIX_INHERITANCE_EA_NAME,
106	SAMBA_XATTR_DOS_ATTRIB,
107	NULL
108};
109
110/****************************************************************************
111 Refuse to allow clients to overwrite our private xattrs.
112****************************************************************************/
113
114static BOOL samba_private_attr_name(const char *unix_ea_name)
115{
116	int i;
117
118	for (i = 0; prohibited_ea_names[i]; i++) {
119		if (strequal( prohibited_ea_names[i], unix_ea_name))
120			return True;
121	}
122	return False;
123}
124
125struct ea_list {
126	struct ea_list *next, *prev;
127	struct ea_struct ea;
128};
129
130/****************************************************************************
131 Get one EA value. Fill in a struct ea_struct.
132****************************************************************************/
133
134static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
135				const char *fname, char *ea_name, struct ea_struct *pea)
136{
137	/* Get the value of this xattr. Max size is 64k. */
138	size_t attr_size = 256;
139	char *val = NULL;
140	ssize_t sizeret;
141
142 again:
143
144	val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
145	if (!val) {
146		return False;
147	}
148
149	if (fsp && fsp->fd != -1) {
150		sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fd, ea_name, val, attr_size);
151	} else {
152		sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
153	}
154
155	if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
156		attr_size = 65536;
157		goto again;
158	}
159
160	if (sizeret == -1) {
161		return False;
162	}
163
164	DEBUG(10,("get_ea_value: EA %s is of length %d: ", ea_name, sizeret));
165	dump_data(10, val, sizeret);
166
167	pea->flags = 0;
168	if (strnequal(ea_name, "user.", 5)) {
169		pea->name = &ea_name[5];
170	} else {
171		pea->name = ea_name;
172	}
173	pea->value.data = (unsigned char *)val;
174	pea->value.length = (size_t)sizeret;
175	return True;
176}
177
178/****************************************************************************
179 Return a linked list of the total EA's. Plus the total size
180****************************************************************************/
181
182static struct ea_list *get_ea_list(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp, const char *fname, size_t *pea_total_len)
183{
184	/* Get a list of all xattrs. Max namesize is 64k. */
185	size_t ea_namelist_size = 1024;
186	char *ea_namelist;
187	char *p;
188	ssize_t sizeret;
189	int i;
190	struct ea_list *ea_list_head = NULL;
191
192	*pea_total_len = 0;
193
194	if (!lp_ea_support(SNUM(conn))) {
195		return NULL;
196	}
197
198	for (i = 0, ea_namelist = TALLOC(mem_ctx, ea_namelist_size); i < 6;
199			ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
200		if (fsp && fsp->fd != -1) {
201			sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fd, ea_namelist, ea_namelist_size);
202		} else {
203			sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
204		}
205
206		if (sizeret == -1 && errno == ERANGE) {
207			ea_namelist_size *= 2;
208		} else {
209			break;
210		}
211	}
212
213	if (sizeret == -1)
214		return NULL;
215
216	DEBUG(10,("get_ea_list: ea_namelist size = %d\n", sizeret ));
217
218	if (sizeret) {
219		for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
220			struct ea_list *listp, *tmp;
221
222			if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
223				continue;
224
225			listp = TALLOC_P(mem_ctx, struct ea_list);
226			if (!listp)
227				return NULL;
228
229			if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
230				return NULL;
231			}
232
233			{
234				fstring dos_ea_name;
235				push_ascii_fstring(dos_ea_name, listp->ea.name);
236				*pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
237				DEBUG(10,("get_ea_list: total_len = %u, %s, val len = %u\n",
238					*pea_total_len, dos_ea_name,
239					(unsigned int)listp->ea.value.length ));
240			}
241			DLIST_ADD_END(ea_list_head, listp, tmp);
242		}
243		/* Add on 4 for total length. */
244		if (*pea_total_len) {
245			*pea_total_len += 4;
246		}
247	}
248
249	DEBUG(10,("get_ea_list: total_len = %u\n", *pea_total_len));
250	return ea_list_head;
251}
252
253/****************************************************************************
254 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
255 that was filled.
256****************************************************************************/
257
258static unsigned int fill_ea_buffer(char *pdata, unsigned int total_data_size,
259	connection_struct *conn, files_struct *fsp, const char *fname)
260{
261	unsigned int ret_data_size = 4;
262	char *p = pdata;
263	size_t total_ea_len;
264	TALLOC_CTX *mem_ctx;
265	struct ea_list *ea_list;
266
267	SMB_ASSERT(total_data_size >= 4);
268
269	SIVAL(pdata,0,0);
270	if (!lp_ea_support(SNUM(conn))) {
271		return 4;
272	}
273	mem_ctx = talloc_init("fill_ea_buffer");
274	if (!mem_ctx) {
275		return 4;
276	}
277
278	ea_list = get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
279	if (!ea_list) {
280		talloc_destroy(mem_ctx);
281		return 4;
282	}
283
284	if (total_ea_len > total_data_size) {
285		talloc_destroy(mem_ctx);
286		return 4;
287	}
288
289	for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
290		size_t dos_namelen;
291		fstring dos_ea_name;
292		push_ascii_fstring(dos_ea_name, ea_list->ea.name);
293		dos_namelen = strlen(dos_ea_name);
294		if (dos_namelen > 255 || dos_namelen == 0) {
295			break;
296		}
297		if (ea_list->ea.value.length > 65535) {
298			break;
299		}
300		if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
301			break;
302		}
303
304		/* We know we have room. */
305		SCVAL(p,0,ea_list->ea.flags);
306		SCVAL(p,1,dos_namelen);
307		SSVAL(p,2,ea_list->ea.value.length);
308		fstrcpy(p+4, dos_ea_name);
309		memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
310
311		total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
312		p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
313	}
314
315	ret_data_size = PTR_DIFF(p, pdata);
316	DEBUG(10,("fill_ea_buffer: data_size = %u, total_ea_len = %u\n",
317			ret_data_size, total_ea_len ));
318	talloc_destroy(mem_ctx);
319	SIVAL(pdata,0,ret_data_size);
320	return ret_data_size;
321}
322
323static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
324{
325	size_t total_ea_len = 0;
326	TALLOC_CTX *mem_ctx = NULL;
327
328	if (!lp_ea_support(SNUM(conn))) {
329		return 0;
330	}
331	mem_ctx = talloc_init("estimate_ea_size");
332	(void)get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
333	talloc_destroy(mem_ctx);
334	return total_ea_len;
335}
336
337/****************************************************************************
338 Ensure the EA name is case insensitive by matching any existing EA name.
339****************************************************************************/
340
341static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
342{
343	size_t total_ea_len;
344	TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
345	struct ea_list *ea_list = get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len);
346
347	for (; ea_list; ea_list = ea_list->next) {
348		if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
349			DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
350				&unix_ea_name[5], ea_list->ea.name));
351			safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
352			break;
353		}
354	}
355	talloc_destroy(mem_ctx);
356}
357
358/****************************************************************************
359 Set or delete an extended attribute.
360****************************************************************************/
361
362static NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname,
363			char *pdata, int total_data)
364{
365	unsigned int namelen;
366	unsigned int ealen;
367	int ret;
368	fstring unix_ea_name;
369
370	if (!lp_ea_support(SNUM(conn))) {
371		return NT_STATUS_EAS_NOT_SUPPORTED;
372	}
373
374	if (total_data < 8) {
375		return NT_STATUS_INVALID_PARAMETER;
376	}
377
378	if (IVAL(pdata,0) > total_data) {
379		DEBUG(10,("set_ea: bad total data size (%u) > %u\n", IVAL(pdata,0), (unsigned int)total_data));
380		return NT_STATUS_INVALID_PARAMETER;
381	}
382
383	pdata += 4;
384	namelen = CVAL(pdata,1);
385	ealen = SVAL(pdata,2);
386	pdata += 4;
387	if (total_data < 8 + namelen + 1 + ealen) {
388		DEBUG(10,("set_ea: bad total data size (%u) < 8 + namelen (%u) + 1 + ealen (%u)\n",
389			(unsigned int)total_data, namelen, ealen));
390		return NT_STATUS_INVALID_PARAMETER;
391	}
392
393	if (pdata[namelen] != '\0') {
394		DEBUG(10,("set_ea: ea name not null terminated\n"));
395		return NT_STATUS_INVALID_PARAMETER;
396	}
397
398	fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
399	pull_ascii(&unix_ea_name[5], pdata, sizeof(fstring) - 5, -1, STR_TERMINATE);
400	pdata += (namelen + 1);
401
402	canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
403
404	DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, ealen));
405	if (ealen) {
406		DEBUG(10,("set_ea: data :\n"));
407		dump_data(10, pdata, ealen);
408	}
409
410	if (samba_private_attr_name(unix_ea_name)) {
411		DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
412		return NT_STATUS_ACCESS_DENIED;
413	}
414
415	if (ealen == 0) {
416		/* Remove the attribute. */
417		if (fsp && (fsp->fd != -1)) {
418			DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
419				unix_ea_name, fsp->fsp_name));
420			ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fd, unix_ea_name);
421		} else {
422			DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
423				unix_ea_name, fname));
424			ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
425		}
426#ifdef ENOATTR
427		/* Removing a non existent attribute always succeeds. */
428		if (ret == -1 && errno == ENOATTR) {
429			DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n", unix_ea_name));
430			ret = 0;
431		}
432#endif
433	} else {
434		if (fsp && (fsp->fd != -1)) {
435			DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
436				unix_ea_name, fsp->fsp_name));
437			ret = SMB_VFS_FSETXATTR(fsp, fsp->fd, unix_ea_name, pdata, ealen, 0);
438		} else {
439			DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
440				unix_ea_name, fname));
441			ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name, pdata, ealen, 0);
442		}
443	}
444
445	if (ret == -1) {
446#ifdef ENOTSUP
447		if (errno == ENOTSUP) {
448			return NT_STATUS_EAS_NOT_SUPPORTED;
449		}
450#endif
451		return map_nt_error_from_unix(errno);
452	}
453
454	return NT_STATUS_OK;
455}
456
457/****************************************************************************
458  Send the required number of replies back.
459  We assume all fields other than the data fields are
460  set correctly for the type of call.
461  HACK ! Always assumes smb_setup field is zero.
462****************************************************************************/
463
464static int send_trans2_replies(char *outbuf,
465			int bufsize,
466			char *params,
467			int paramsize,
468			char *pdata,
469			int datasize)
470{
471	/* As we are using a protocol > LANMAN1 then the max_send
472	 variable must have been set in the sessetupX call.
473	 This takes precedence over the max_xmit field in the
474	 global struct. These different max_xmit variables should
475	 be merged as this is now too confusing */
476
477	extern int max_send;
478	int data_to_send = datasize;
479	int params_to_send = paramsize;
480	int useable_space;
481	char *pp = params;
482	char *pd = pdata;
483	int params_sent_thistime, data_sent_thistime, total_sent_thistime;
484	int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
485	int data_alignment_offset = 0;
486
487	/* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
488
489	set_message(outbuf,10,0,True);
490
491	/* If there genuinely are no parameters or data to send just send the empty packet */
492
493	if(params_to_send == 0 && data_to_send == 0) {
494		if (!send_smb(smbd_server_fd(),outbuf))
495			exit_server("send_trans2_replies: send_smb failed.");
496		return 0;
497	}
498
499	/* When sending params and data ensure that both are nicely aligned */
500	/* Only do this alignment when there is also data to send - else
501		can cause NT redirector problems. */
502
503	if (((params_to_send % 4) != 0) && (data_to_send != 0))
504		data_alignment_offset = 4 - (params_to_send % 4);
505
506	/* Space is bufsize minus Netbios over TCP header minus SMB header */
507	/* The alignment_offset is to align the param bytes on an even byte
508		boundary. NT 4.0 Beta needs this to work correctly. */
509
510	useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
511
512	/* useable_space can never be more than max_send minus the alignment offset. */
513
514	useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
515
516	while (params_to_send || data_to_send) {
517		/* Calculate whether we will totally or partially fill this packet */
518
519		total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
520
521		/* We can never send more than useable_space */
522		/*
523		 * Note that 'useable_space' does not include the alignment offsets,
524		 * but we must include the alignment offsets in the calculation of
525		 * the length of the data we send over the wire, as the alignment offsets
526		 * are sent here. Fix from Marc_Jacobsen@hp.com.
527		 */
528
529		total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
530
531		set_message(outbuf, 10, total_sent_thistime, True);
532
533		/* Set total params and data to be sent */
534		SSVAL(outbuf,smb_tprcnt,paramsize);
535		SSVAL(outbuf,smb_tdrcnt,datasize);
536
537		/* Calculate how many parameters and data we can fit into
538		 * this packet. Parameters get precedence
539		 */
540
541		params_sent_thistime = MIN(params_to_send,useable_space);
542		data_sent_thistime = useable_space - params_sent_thistime;
543		data_sent_thistime = MIN(data_sent_thistime,data_to_send);
544
545		SSVAL(outbuf,smb_prcnt, params_sent_thistime);
546
547		/* smb_proff is the offset from the start of the SMB header to the
548			parameter bytes, however the first 4 bytes of outbuf are
549			the Netbios over TCP header. Thus use smb_base() to subtract
550			them from the calculation */
551
552		SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
553
554		if(params_sent_thistime == 0)
555			SSVAL(outbuf,smb_prdisp,0);
556		else
557			/* Absolute displacement of param bytes sent in this packet */
558			SSVAL(outbuf,smb_prdisp,pp - params);
559
560		SSVAL(outbuf,smb_drcnt, data_sent_thistime);
561		if(data_sent_thistime == 0) {
562			SSVAL(outbuf,smb_droff,0);
563			SSVAL(outbuf,smb_drdisp, 0);
564		} else {
565			/* The offset of the data bytes is the offset of the
566				parameter bytes plus the number of parameters being sent this time */
567			SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) -
568				smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
569			SSVAL(outbuf,smb_drdisp, pd - pdata);
570		}
571
572		/* Copy the param bytes into the packet */
573
574		if(params_sent_thistime)
575			memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
576
577		/* Copy in the data bytes */
578		if(data_sent_thistime)
579			memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
580				data_alignment_offset,pd,data_sent_thistime);
581
582		DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
583			params_sent_thistime, data_sent_thistime, useable_space));
584		DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
585			params_to_send, data_to_send, paramsize, datasize));
586
587		/* Send the packet */
588		if (!send_smb(smbd_server_fd(),outbuf))
589			exit_server("send_trans2_replies: send_smb failed.");
590
591		pp += params_sent_thistime;
592		pd += data_sent_thistime;
593
594		params_to_send -= params_sent_thistime;
595		data_to_send -= data_sent_thistime;
596
597		/* Sanity check */
598		if(params_to_send < 0 || data_to_send < 0) {
599			DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
600				params_to_send, data_to_send));
601			return -1;
602		}
603	}
604
605	return 0;
606}
607
608/****************************************************************************
609 Reply to a TRANSACT2_OPEN.
610****************************************************************************/
611
612static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
613				char **pparams, int total_params, char **ppdata, int total_data,
614				unsigned int max_data_bytes)
615{
616	char *params = *pparams;
617	int16 open_mode;
618	int16 open_attr;
619	BOOL oplock_request;
620#if 0
621	BOOL return_additional_info;
622	int16 open_sattr;
623	time_t open_time;
624#endif
625	int16 open_ofun;
626	int32 open_size;
627	char *pname;
628	pstring fname;
629	SMB_OFF_T size=0;
630	int fmode=0,mtime=0,rmode;
631	SMB_INO_T inode = 0;
632	SMB_STRUCT_STAT sbuf;
633	int smb_action = 0;
634	BOOL bad_path = False;
635	files_struct *fsp;
636	NTSTATUS status;
637
638	/*
639	 * Ensure we have enough parameters to perform the operation.
640	 */
641
642	if (total_params < 29)
643		return(ERROR_DOS(ERRDOS,ERRinvalidparam));
644
645	open_mode = SVAL(params, 2);
646	open_attr = SVAL(params,6);
647	oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
648#if 0
649	return_additional_info = BITSETW(params,0);
650	open_sattr = SVAL(params, 4);
651	open_time = make_unix_date3(params+8);
652#endif
653	open_ofun = SVAL(params,12);
654	open_size = IVAL(params,14);
655	pname = &params[28];
656
657	if (IS_IPC(conn))
658		return(ERROR_DOS(ERRSRV,ERRaccess));
659
660	srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status, False);
661	if (!NT_STATUS_IS_OK(status)) {
662		return ERROR_NT(status);
663	}
664
665	DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n",
666		fname,open_mode, open_attr, open_ofun, open_size));
667
668	/* XXXX we need to handle passed times, sattr and flags */
669
670	unix_convert(fname,conn,0,&bad_path,&sbuf);
671	if (bad_path) {
672		return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
673	}
674
675	if (!check_name(fname,conn)) {
676		return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
677	}
678
679	fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,(uint32)open_attr,
680		oplock_request, &rmode,&smb_action);
681
682	if (!fsp) {
683		if (open_was_deferred(SVAL(inbuf,smb_mid))) {
684			/* We have re-scheduled this call. */
685			clear_cached_errors();
686			return -1;
687		}
688		return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
689	}
690
691	size = get_file_size(sbuf);
692	fmode = dos_mode(conn,fname,&sbuf);
693	mtime = sbuf.st_mtime;
694	inode = sbuf.st_ino;
695	if (fmode & aDIR) {
696		close_file(fsp,False);
697		return(ERROR_DOS(ERRDOS,ERRnoaccess));
698	}
699
700	/* Realloc the size of parameters and data we will return */
701	params = SMB_REALLOC(*pparams, 28);
702	if( params == NULL )
703		return(ERROR_DOS(ERRDOS,ERRnomem));
704	*pparams = params;
705
706	memset((char *)params,'\0',28);
707	SSVAL(params,0,fsp->fnum);
708	SSVAL(params,2,fmode);
709	put_dos_date2(params,4, mtime);
710	SIVAL(params,8, (uint32)size);
711	SSVAL(params,12,rmode);
712
713	if (oplock_request && lp_fake_oplocks(SNUM(conn)))
714		smb_action |= EXTENDED_OPLOCK_GRANTED;
715
716	SSVAL(params,18,smb_action);
717
718	/*
719	 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
720	 */
721	SIVAL(params,20,inode);
722
723	/* Send the required number of replies */
724	send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0);
725
726	return -1;
727}
728
729/*********************************************************
730 Routine to check if a given string matches exactly.
731 as a special case a mask of "." does NOT match. That
732 is required for correct wildcard semantics
733 Case can be significant or not.
734**********************************************************/
735
736static BOOL exact_match(char *str,char *mask, BOOL case_sig)
737{
738	if (mask[0] == '.' && mask[1] == 0)
739		return False;
740	if (case_sig)
741		return strcmp(str,mask)==0;
742	if (StrCaseCmp(str,mask) != 0) {
743		return False;
744	}
745	if (ms_has_wild(str)) {
746		return False;
747	}
748	return True;
749}
750
751/****************************************************************************
752 Return the filetype for UNIX extensions.
753****************************************************************************/
754
755static uint32 unix_filetype(mode_t mode)
756{
757	if(S_ISREG(mode))
758		return UNIX_TYPE_FILE;
759	else if(S_ISDIR(mode))
760		return UNIX_TYPE_DIR;
761#ifdef S_ISLNK
762	else if(S_ISLNK(mode))
763		return UNIX_TYPE_SYMLINK;
764#endif
765#ifdef S_ISCHR
766	else if(S_ISCHR(mode))
767		return UNIX_TYPE_CHARDEV;
768#endif
769#ifdef S_ISBLK
770	else if(S_ISBLK(mode))
771		return UNIX_TYPE_BLKDEV;
772#endif
773#ifdef S_ISFIFO
774	else if(S_ISFIFO(mode))
775		return UNIX_TYPE_FIFO;
776#endif
777#ifdef S_ISSOCK
778	else if(S_ISSOCK(mode))
779		return UNIX_TYPE_SOCKET;
780#endif
781
782	DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
783	return UNIX_TYPE_UNKNOWN;
784}
785
786/****************************************************************************
787 Map wire perms onto standard UNIX permissions. Obey share restrictions.
788****************************************************************************/
789
790static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
791{
792	mode_t ret = 0;
793
794	if (perms == SMB_MODE_NO_CHANGE)
795		return pst->st_mode;
796
797	ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
798	ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
799	ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
800	ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
801	ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
802	ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
803	ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
804	ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
805	ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
806#ifdef S_ISVTX
807	ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
808#endif
809#ifdef S_ISGID
810	ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
811#endif
812#ifdef S_ISUID
813	ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
814#endif
815
816	if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
817		ret &= lp_dir_mask(SNUM(conn));
818		/* Add in force bits */
819		ret |= lp_force_dir_mode(SNUM(conn));
820	} else {
821		/* Apply mode mask */
822		ret &= lp_create_mask(SNUM(conn));
823		/* Add in force bits */
824		ret |= lp_force_create_mode(SNUM(conn));
825	}
826
827	return ret;
828}
829
830/****************************************************************************
831 Get a level dependent lanman2 dir entry.
832****************************************************************************/
833
834static BOOL get_lanman2_dir_entry(connection_struct *conn,
835				  void *inbuf, void *outbuf,
836				 char *path_mask,int dirtype,int info_level,
837				 int requires_resume_key,
838				 BOOL dont_descend,char **ppdata,
839				 char *base_data, int space_remaining,
840				 BOOL *out_of_space, BOOL *got_exact_match,
841				 int *last_entry_off)
842{
843	const char *dname;
844	BOOL found = False;
845	SMB_STRUCT_STAT sbuf;
846	pstring mask;
847	pstring pathreal;
848	pstring fname;
849	char *p, *q, *pdata = *ppdata;
850	uint32 reskey=0;
851	long prev_dirpos=0;
852	int mode=0;
853    /* Foxconn modified start pling 11/23/2009 */
854	//SMB_OFF_T file_size = 0;
855	SMB_BIG_UINT file_size = 0;
856    /* Foxconn modified start pling 11/23/2009 */
857	SMB_BIG_UINT allocation_size = 0;
858	uint32 len;
859	time_t mdate=0, adate=0, cdate=0;
860	char *nameptr;
861	char *last_entry_ptr;
862	BOOL was_8_3;
863	int nt_extmode; /* Used for NT connections instead of mode */
864	BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
865
866	*fname = 0;
867	*out_of_space = False;
868	*got_exact_match = False;
869
870	if (!conn->dirptr)
871		return(False);
872
873	p = strrchr_m(path_mask,'/');
874	if(p != NULL) {
875		if(p[1] == '\0')
876			pstrcpy(mask,"*.*");
877		else
878			pstrcpy(mask, p+1);
879	} else
880		pstrcpy(mask, path_mask);
881
882
883	while (!found) {
884		BOOL got_match;
885		/* Needed if we run out of space */
886		long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
887		dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
888
889		/*
890		 * Due to bugs in NT client redirectors we are not using
891		 * resume keys any more - set them to zero.
892		 * Check out the related comments in findfirst/findnext.
893		 * JRA.
894		 */
895
896		reskey = 0;
897
898		DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
899			(long)conn->dirptr,curr_dirpos));
900
901		if (!dname)
902			return(False);
903
904		pstrcpy(fname,dname);
905
906		if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive)))
907			got_match = mask_match(fname, mask, conn->case_sensitive);
908
909		if(!got_match && !mangle_is_8_3(fname, False)) {
910
911			/*
912			 * It turns out that NT matches wildcards against
913			 * both long *and* short names. This may explain some
914			 * of the wildcard wierdness from old DOS clients
915			 * that some people have been seeing.... JRA.
916			 */
917
918			pstring newname;
919			pstrcpy( newname, fname);
920			mangle_map( newname, True, False, SNUM(conn));
921			if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive)))
922				got_match = mask_match(newname, mask, conn->case_sensitive);
923		}
924
925		if(got_match) {
926			BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
927			if (dont_descend && !isdots)
928				continue;
929
930			pstrcpy(pathreal,conn->dirpath);
931			if(needslash)
932				pstrcat(pathreal,"/");
933			pstrcat(pathreal,dname);
934
935			if (INFO_LEVEL_IS_UNIX(info_level)) {
936				if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
937					DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
938						pathreal,strerror(errno)));
939					continue;
940				}
941			} else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
942
943				/* Needed to show the msdfs symlinks as
944				 * directories */
945
946				if(lp_host_msdfs() &&
947				   lp_msdfs_root(SNUM(conn)) &&
948				   is_msdfs_link(conn, pathreal, NULL, NULL,
949						 &sbuf)) {
950
951					DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
952					sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
953
954				} else {
955
956					DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
957						pathreal,strerror(errno)));
958					continue;
959				}
960			}
961
962			mode = dos_mode(conn,pathreal,&sbuf);
963
964			if (!dir_check_ftype(conn,mode,dirtype)) {
965				DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
966				continue;
967			}
968
969			file_size = get_file_size(sbuf);
970			allocation_size = get_allocation_size(conn,NULL,&sbuf);
971			mdate = sbuf.st_mtime;
972			adate = sbuf.st_atime;
973			cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
974
975			if (lp_dos_filetime_resolution(SNUM(conn))) {
976				cdate &= ~1;
977				mdate &= ~1;
978				adate &= ~1;
979			}
980
981			if(mode & aDIR) {
982				/* This is necessary, as otherwise the
983				 * desktop.ini file in this folder is
984				 * ignored */
985				mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
986				file_size = 0;
987			}
988
989			DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
990
991			found = True;
992		}
993	}
994
995	mangle_map(fname,False,True,SNUM(conn));
996
997	p = pdata;
998	last_entry_ptr = p;
999
1000	nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1001
1002	switch (info_level) {
1003		case SMB_INFO_STANDARD:
1004			DEBUG(10,("get_lanman2_dir_entry: SMB_INFO_STANDARD\n"));
1005			if(requires_resume_key) {
1006				SIVAL(p,0,reskey);
1007				p += 4;
1008			}
1009			put_dos_date2(p,l1_fdateCreation,cdate);
1010			put_dos_date2(p,l1_fdateLastAccess,adate);
1011			put_dos_date2(p,l1_fdateLastWrite,mdate);
1012			SIVAL(p,l1_cbFile,(uint32)file_size);
1013			SIVAL(p,l1_cbFileAlloc,(uint32)allocation_size);
1014			SSVAL(p,l1_attrFile,mode);
1015			p += l1_achName;
1016			nameptr = p;
1017			p += align_string(outbuf, p, 0);
1018			len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1019			if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1020				if (len > 2) {
1021					SCVAL(nameptr, -1, len - 2);
1022				} else {
1023					SCVAL(nameptr, -1, 0);
1024				}
1025			} else {
1026				if (len > 1) {
1027					SCVAL(nameptr, -1, len - 1);
1028				} else {
1029					SCVAL(nameptr, -1, 0);
1030				}
1031			}
1032			p += len;
1033			break;
1034
1035		case SMB_INFO_QUERY_EA_SIZE:
1036			DEBUG(10,("get_lanman2_dir_entry: SMB_INFO_QUERY_EA_SIZE\n"));
1037			if(requires_resume_key) {
1038				SIVAL(p,0,reskey);
1039				p += 4;
1040			}
1041			put_dos_date2(p,l2_fdateCreation,cdate);
1042			put_dos_date2(p,l2_fdateLastAccess,adate);
1043			put_dos_date2(p,l2_fdateLastWrite,mdate);
1044			SIVAL(p,l2_cbFile,(uint32)file_size);
1045			SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size);
1046			SSVAL(p,l2_attrFile,mode);
1047			{
1048				unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1049				SIVAL(p,l2_cbList,ea_size); /* Extended attributes */
1050			}
1051			p += l2_achName;
1052			nameptr = p - 1;
1053			len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1054			if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1055				if (len > 2) {
1056					len -= 2;
1057				} else {
1058					len = 0;
1059				}
1060			} else {
1061				if (len > 1) {
1062					len -= 1;
1063				} else {
1064					len = 0;
1065				}
1066			}
1067			SCVAL(nameptr,0,len);
1068			p += len;
1069			SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1070			break;
1071
1072		case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1073			DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1074			was_8_3 = mangle_is_8_3(fname, True);
1075			p += 4;
1076			SIVAL(p,0,reskey); p += 4;
1077			put_long_date(p,cdate); p += 8;
1078			put_long_date(p,adate); p += 8;
1079			put_long_date(p,mdate); p += 8;
1080			put_long_date(p,mdate); p += 8;
1081            /* Foxconn modified start pling 11/23/2009 */
1082			//SOFF_T(p,0,file_size); p += 8;
1083			SOFF64_T(p,0,file_size); p += 8;
1084            /* Foxconn modified end pling 11/23/2009 */
1085			/* Foxconn modified start pling 03/11/2011 */
1086			/* Fix potential incorrect file size issue where file size > 4GB. */
1087			/* SOFF_T(p,0,allocation_size); p += 8; */
1088			SOFF64_T(p,0,allocation_size); p += 8;
1089			/* Foxconn modified end pling 03/11/2011 */
1090			SIVAL(p,0,nt_extmode); p += 4;
1091			q = p; p += 4; /* q is placeholder for name length. */
1092			{
1093				unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1094				SIVAL(p,0,ea_size); /* Extended attributes */
1095				p += 4;
1096			}
1097			/* Clear the short name buffer. This is
1098			 * IMPORTANT as not doing so will trigger
1099			 * a Win2k client bug. JRA.
1100			 */
1101			memset(p,'\0',26);
1102			if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1103				pstring mangled_name;
1104				pstrcpy(mangled_name, fname);
1105				mangle_map(mangled_name,True,True,SNUM(conn));
1106				mangled_name[12] = 0;
1107				len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1108				SSVAL(p, 0, len);
1109			} else {
1110				SSVAL(p,0,0);
1111				*(p+2) = 0;
1112			}
1113			p += 2 + 24;
1114			len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1115			SIVAL(q,0,len);
1116			p += len;
1117			len = PTR_DIFF(p, pdata);
1118			len = (len + 3) & ~3;
1119			SIVAL(pdata,0,len);
1120			p = pdata + len;
1121			break;
1122
1123		case SMB_FIND_FILE_DIRECTORY_INFO:
1124			DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1125			p += 4;
1126			SIVAL(p,0,reskey); p += 4;
1127			put_long_date(p,cdate); p += 8;
1128			put_long_date(p,adate); p += 8;
1129			put_long_date(p,mdate); p += 8;
1130			put_long_date(p,mdate); p += 8;
1131			/* Foxconn modified start pling 03/11/2011 */
1132			/* Fix potential incorrect file size issue if file size > 4GB. */
1133#if 0
1134			SOFF_T(p,0,file_size); p += 8;
1135			SOFF_T(p,0,allocation_size); p += 8;
1136#endif
1137			SOFF64_T(p,0,file_size); p += 8;
1138			SOFF64_T(p,0,allocation_size); p += 8;
1139			/* Foxconn modified end pling 03/11/2011 */
1140			SIVAL(p,0,nt_extmode); p += 4;
1141			len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1142			SIVAL(p,0,len);
1143			p += 4 + len;
1144			len = PTR_DIFF(p, pdata);
1145			len = (len + 3) & ~3;
1146			SIVAL(pdata,0,len);
1147			p = pdata + len;
1148			break;
1149
1150		case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1151			DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1152			p += 4;
1153			SIVAL(p,0,reskey); p += 4;
1154			put_long_date(p,cdate); p += 8;
1155			put_long_date(p,adate); p += 8;
1156			put_long_date(p,mdate); p += 8;
1157			put_long_date(p,mdate); p += 8;
1158			/* Foxconn modified start pling 03/11/2011 */
1159			/* Fix Win7 DOS prompt can't get correct file size > 4GB */
1160#if 0
1161			SOFF_T(p,0,file_size); p += 8;
1162			SOFF_T(p,0,allocation_size); p += 8;
1163#endif
1164			SOFF64_T(p,0,file_size); p += 8;
1165			SOFF64_T(p,0,allocation_size); p += 8;
1166			/* Foxconn modified end pling 03/11/2011 */
1167			SIVAL(p,0,nt_extmode); p += 4;
1168			q = p; p += 4; /* q is placeholder for name length. */
1169			{
1170				unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1171				SIVAL(p,0,ea_size); /* Extended attributes */
1172				p +=4;
1173			}
1174			len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1175			SIVAL(q, 0, len);
1176			p += len;
1177
1178			len = PTR_DIFF(p, pdata);
1179			len = (len + 3) & ~3;
1180			SIVAL(pdata,0,len);
1181			p = pdata + len;
1182			break;
1183
1184		case SMB_FIND_FILE_NAMES_INFO:
1185			DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1186			p += 4;
1187			SIVAL(p,0,reskey); p += 4;
1188			p += 4;
1189			/* this must *not* be null terminated or w2k gets in a loop trying to set an
1190			   acl on a dir (tridge) */
1191			len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1192			SIVAL(p, -4, len);
1193			p += len;
1194			len = PTR_DIFF(p, pdata);
1195			len = (len + 3) & ~3;
1196			SIVAL(pdata,0,len);
1197			p = pdata + len;
1198			break;
1199
1200		case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1201			DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1202			p += 4;
1203			SIVAL(p,0,reskey); p += 4;
1204			put_long_date(p,cdate); p += 8;
1205			put_long_date(p,adate); p += 8;
1206			put_long_date(p,mdate); p += 8;
1207			put_long_date(p,mdate); p += 8;
1208			/* Foxconn modified start pling 03/11/2011 */
1209			/* Fix potential incorrect file size issue if file size > 4GB. */
1210#if 0
1211			SOFF_T(p,0,file_size); p += 8;
1212			SOFF_T(p,0,allocation_size); p += 8;
1213#endif
1214			SOFF64_T(p,0,file_size); p += 8;
1215			SOFF64_T(p,0,allocation_size); p += 8;
1216			/* Foxconn modified end pling 03/11/2011 */
1217			SIVAL(p,0,nt_extmode); p += 4;
1218			q = p; p += 4; /* q is placeholder for name length. */
1219			{
1220				unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1221				SIVAL(p,0,ea_size); /* Extended attributes */
1222				p +=4;
1223			}
1224			SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1225			SIVAL(p,0,sbuf.st_dev); p += 4;
1226			SIVAL(p,0,sbuf.st_ino); p += 4;
1227			len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1228			SIVAL(q, 0, len);
1229			p += len;
1230			len = PTR_DIFF(p, pdata);
1231			len = (len + 3) & ~3;
1232			SIVAL(pdata,0,len);
1233			p = pdata + len;
1234			break;
1235
1236		case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1237			DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1238			was_8_3 = mangle_is_8_3(fname, True);
1239			p += 4;
1240			SIVAL(p,0,reskey); p += 4;
1241			put_long_date(p,cdate); p += 8;
1242			put_long_date(p,adate); p += 8;
1243			put_long_date(p,mdate); p += 8;
1244			put_long_date(p,mdate); p += 8;
1245			/* Foxconn modified start pling 03/11/2011 */
1246			/* Fix potential incorrect file size issue if file size > 4GB. */
1247#if 0
1248			SOFF_T(p,0,file_size); p += 8;
1249			SOFF_T(p,0,allocation_size); p += 8;
1250#endif
1251			SOFF64_T(p,0,file_size); p += 8;
1252			SOFF64_T(p,0,allocation_size); p += 8;
1253			/* Foxconn modified end pling 03/11/2011 */
1254			SIVAL(p,0,nt_extmode); p += 4;
1255			q = p; p += 4; /* q is placeholder for name length */
1256			{
1257				unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1258				SIVAL(p,0,ea_size); /* Extended attributes */
1259				p +=4;
1260			}
1261			/* Clear the short name buffer. This is
1262			 * IMPORTANT as not doing so will trigger
1263			 * a Win2k client bug. JRA.
1264			 */
1265			memset(p,'\0',26);
1266			if (!was_8_3 && lp_manglednames(SNUM(conn))) {
1267				pstring mangled_name;
1268				pstrcpy(mangled_name, fname);
1269				mangle_map(mangled_name,True,True,SNUM(conn));
1270				mangled_name[12] = 0;
1271				len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1272				SSVAL(p, 0, len);
1273			} else {
1274				SSVAL(p,0,0);
1275				*(p+2) = 0;
1276			}
1277			p += 26;
1278			SSVAL(p,0,0); p += 2; /* Reserved ? */
1279			SIVAL(p,0,sbuf.st_dev); p += 4;
1280			SIVAL(p,0,sbuf.st_ino); p += 4;
1281			len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1282			SIVAL(q,0,len);
1283			p += len;
1284			len = PTR_DIFF(p, pdata);
1285			len = (len + 3) & ~3;
1286			SIVAL(pdata,0,len);
1287			p = pdata + len;
1288			break;
1289
1290		/* CIFS UNIX Extension. */
1291
1292		case SMB_FIND_FILE_UNIX:
1293			DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1294			p+= 4;
1295			SIVAL(p,0,reskey); p+= 4;    /* Used for continuing search. */
1296
1297			/* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1298			/* Foxconn modified start pling 03/11/2011 */
1299			/* Fix potential incorrect file size issue if file size > 4GB */
1300			/* SOFF_T(p,0,get_file_size(sbuf)); */            /* File size 64 Bit */
1301			SOFF64_T(p,0,get_file_size(sbuf));             /* File size 64 Bit */
1302			/* Foxconn modified end pling 03/11/2011 */
1303			p+= 8;
1304
1305			/* Foxconn modified start pling 03/11/2011 */
1306			/* Fix potential incorrect file size issue if file size > 4GB */
1307			/* SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); */ /* Number of bytes used on disk - 64 Bit */
1308			SOFF64_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1309			/* Foxconn modified end pling 03/11/2011 */
1310			p+= 8;
1311
1312			put_long_date(p,sbuf.st_ctime);       /* Inode change Time 64 Bit */
1313			put_long_date(p+8,sbuf.st_atime);     /* Last access time 64 Bit */
1314			put_long_date(p+16,sbuf.st_mtime);    /* Last modification time 64 Bit */
1315			p+= 24;
1316
1317			SIVAL(p,0,sbuf.st_uid);               /* user id for the owner */
1318			SIVAL(p,4,0);
1319			p+= 8;
1320
1321			SIVAL(p,0,sbuf.st_gid);               /* group id of owner */
1322			SIVAL(p,4,0);
1323			p+= 8;
1324
1325			SIVAL(p,0,unix_filetype(sbuf.st_mode));
1326			p+= 4;
1327
1328			SIVAL(p,0,unix_dev_major(sbuf.st_rdev));   /* Major device number if type is device */
1329			SIVAL(p,4,0);
1330			p+= 8;
1331
1332			SIVAL(p,0,unix_dev_minor(sbuf.st_rdev));   /* Minor device number if type is device */
1333			SIVAL(p,4,0);
1334			p+= 8;
1335
1336			SINO_T(p,0,(SMB_INO_T)sbuf.st_ino);   /* inode number */
1337			p+= 8;
1338
1339			SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode));     /* Standard UNIX file permissions */
1340			SIVAL(p,4,0);
1341			p+= 8;
1342
1343			SIVAL(p,0,sbuf.st_nlink);             /* number of hard links */
1344			SIVAL(p,4,0);
1345			p+= 8;
1346
1347			len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1348			p += len;
1349
1350			len = PTR_DIFF(p, pdata);
1351			len = (len + 3) & ~3;
1352			SIVAL(pdata,0,len);	/* Offset from this structure to the beginning of the next one */
1353			p = pdata + len;
1354			/* End of SMB_QUERY_FILE_UNIX_BASIC */
1355
1356			break;
1357
1358		default:
1359			return(False);
1360	}
1361
1362
1363	if (PTR_DIFF(p,pdata) > space_remaining) {
1364		/* Move the dirptr back to prev_dirpos */
1365		dptr_SeekDir(conn->dirptr, prev_dirpos);
1366		*out_of_space = True;
1367		DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1368		return False; /* Not finished - just out of space */
1369	}
1370
1371	/* Setup the last entry pointer, as an offset from base_data */
1372	*last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1373	/* Advance the data pointer to the next slot */
1374	*ppdata = p;
1375
1376	return(found);
1377}
1378
1379/****************************************************************************
1380 Reply to a TRANS2_FINDFIRST.
1381****************************************************************************/
1382
1383static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
1384				char **pparams, int total_params, char **ppdata, int total_data,
1385				unsigned int max_data_bytes)
1386{
1387	/* We must be careful here that we don't return more than the
1388		allowed number of data bytes. If this means returning fewer than
1389		maxentries then so be it. We assume that the redirector has
1390		enough room for the fixed number of parameter bytes it has
1391		requested. */
1392	char *params = *pparams;
1393	char *pdata = *ppdata;
1394	int dirtype = SVAL(params,0);
1395	int maxentries = SVAL(params,2);
1396	uint16 findfirst_flags = SVAL(params,4);
1397	BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1398	BOOL close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1399	BOOL requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1400	int info_level = SVAL(params,6);
1401	pstring directory;
1402	pstring mask;
1403	char *p;
1404	int last_entry_off=0;
1405	int dptr_num = -1;
1406	int numentries = 0;
1407	int i;
1408	BOOL finished = False;
1409	BOOL dont_descend = False;
1410	BOOL out_of_space = False;
1411	int space_remaining;
1412	BOOL bad_path = False;
1413	SMB_STRUCT_STAT sbuf;
1414	NTSTATUS ntstatus = NT_STATUS_OK;
1415
1416	if (total_params < 12)
1417		return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1418
1419	*directory = *mask = 0;
1420
1421	DEBUG(3,("call_trans2findfirst: dirtype = %d, maxentries = %d, close_after_first=%d, \
1422close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1423		dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1424		info_level, max_data_bytes));
1425
1426	if (!maxentries) {
1427		/* W2K3 seems to treat zero as 1. */
1428		maxentries = 1;
1429	}
1430
1431	switch (info_level) {
1432		case SMB_INFO_STANDARD:
1433		case SMB_INFO_QUERY_EA_SIZE:
1434		case SMB_FIND_FILE_DIRECTORY_INFO:
1435		case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1436		case SMB_FIND_FILE_NAMES_INFO:
1437		case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1438		case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1439		case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1440			break;
1441		case SMB_FIND_FILE_UNIX:
1442			if (!lp_unix_extensions())
1443				return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1444			break;
1445		default:
1446			return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1447	}
1448
1449	srvstr_get_path(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, True);
1450	if (!NT_STATUS_IS_OK(ntstatus)) {
1451		return ERROR_NT(ntstatus);
1452	}
1453
1454	RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
1455
1456	unix_convert(directory,conn,0,&bad_path,&sbuf);
1457	if (bad_path) {
1458		return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1459	}
1460	if(!check_name(directory,conn)) {
1461		return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1462	}
1463
1464	p = strrchr_m(directory,'/');
1465	if(p == NULL) {
1466		/* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1467		if((directory[0] == '.') && (directory[1] == '\0'))
1468			pstrcpy(mask,"*");
1469		else
1470			pstrcpy(mask,directory);
1471		pstrcpy(directory,"./");
1472	} else {
1473		pstrcpy(mask,p+1);
1474		*p = 0;
1475	}
1476
1477	DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1478
1479	pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1480	if( pdata == NULL )
1481		return(ERROR_DOS(ERRDOS,ERRnomem));
1482
1483	*ppdata = pdata;
1484	memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1485
1486	/* Realloc the params space */
1487	params = SMB_REALLOC(*pparams, 10);
1488	if (params == NULL)
1489		return ERROR_DOS(ERRDOS,ERRnomem);
1490	*pparams = params;
1491
1492	dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
1493	if (dptr_num < 0)
1494		return(UNIXERROR(ERRDOS,ERRbadfile));
1495
1496	/* Save the wildcard match and attribs we are using on this directory -
1497		needed as lanman2 assumes these are being saved between calls */
1498
1499	if (!dptr_set_wcard_and_attributes(dptr_num, mask, dirtype)) {
1500		dptr_close(&dptr_num);
1501		return ERROR_DOS(ERRDOS,ERRnomem);
1502	}
1503
1504	DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
1505
1506	/* We don't need to check for VOL here as this is returned by
1507		a different TRANS2 call. */
1508
1509	DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1510	if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1511		dont_descend = True;
1512
1513	p = pdata;
1514	space_remaining = max_data_bytes;
1515	out_of_space = False;
1516
1517	for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1518		BOOL got_exact_match = False;
1519
1520		/* this is a heuristic to avoid seeking the dirptr except when
1521			absolutely necessary. It allows for a filename of about 40 chars */
1522		if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1523			out_of_space = True;
1524			finished = False;
1525		} else {
1526			finished = !get_lanman2_dir_entry(conn,
1527					inbuf, outbuf,
1528					mask,dirtype,info_level,
1529					requires_resume_key,dont_descend,
1530					&p,pdata,space_remaining, &out_of_space, &got_exact_match,
1531					&last_entry_off);
1532		}
1533
1534		if (finished && out_of_space)
1535			finished = False;
1536
1537		if (!finished && !out_of_space)
1538			numentries++;
1539
1540		/*
1541		 * As an optimisation if we know we aren't looking
1542		 * for a wildcard name (ie. the name matches the wildcard exactly)
1543		 * then we can finish on any (first) match.
1544		 * This speeds up large directory searches. JRA.
1545		 */
1546
1547		if(got_exact_match)
1548			finished = True;
1549
1550		space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1551	}
1552
1553	/* Check if we can close the dirptr */
1554	if(close_after_first || (finished && close_if_end)) {
1555		DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1556		dptr_close(&dptr_num);
1557	}
1558
1559	/*
1560	 * If there are no matching entries we must return ERRDOS/ERRbadfile -
1561	 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1562	 * the protocol level is less than NT1. Tested with smbclient. JRA.
1563	 * This should fix the OS/2 client bug #2335.
1564	 */
1565
1566	if(numentries == 0) {
1567		dptr_close(&dptr_num);
1568		if (Protocol < PROTOCOL_NT1) {
1569			return ERROR_DOS(ERRDOS,ERRnofiles);
1570		} else {
1571			return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1572		}
1573	}
1574
1575	/* At this point pdata points to numentries directory entries. */
1576
1577	/* Set up the return parameter block */
1578	SSVAL(params,0,dptr_num);
1579	SSVAL(params,2,numentries);
1580	SSVAL(params,4,finished);
1581	SSVAL(params,6,0); /* Never an EA error */
1582	SSVAL(params,8,last_entry_off);
1583
1584	send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1585
1586	if ((! *directory) && dptr_path(dptr_num))
1587		slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1588
1589	DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1590		smb_fn_name(CVAL(inbuf,smb_com)),
1591		mask, directory, dirtype, numentries ) );
1592
1593	/*
1594	 * Force a name mangle here to ensure that the
1595	 * mask as an 8.3 name is top of the mangled cache.
1596	 * The reasons for this are subtle. Don't remove
1597	 * this code unless you know what you are doing
1598	 * (see PR#13758). JRA.
1599	 */
1600
1601	if(!mangle_is_8_3_wildcards( mask, False))
1602		mangle_map(mask, True, True, SNUM(conn));
1603
1604	return(-1);
1605}
1606
1607/****************************************************************************
1608 Reply to a TRANS2_FINDNEXT.
1609****************************************************************************/
1610
1611static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1612					char **pparams, int total_params, char **ppdata, int total_data,
1613					unsigned int max_data_bytes)
1614{
1615	/* We must be careful here that we don't return more than the
1616		allowed number of data bytes. If this means returning fewer than
1617		maxentries then so be it. We assume that the redirector has
1618		enough room for the fixed number of parameter bytes it has
1619		requested. */
1620	char *params = *pparams;
1621	char *pdata = *ppdata;
1622	int dptr_num = SVAL(params,0);
1623	int maxentries = SVAL(params,2);
1624	uint16 info_level = SVAL(params,4);
1625	uint32 resume_key = IVAL(params,6);
1626	uint16 findnext_flags = SVAL(params,10);
1627	BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1628	BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1629	BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1630	BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1631	pstring resume_name;
1632	pstring mask;
1633	pstring directory;
1634	char *p;
1635	uint16 dirtype;
1636	int numentries = 0;
1637	int i, last_entry_off=0;
1638	BOOL finished = False;
1639	BOOL dont_descend = False;
1640	BOOL out_of_space = False;
1641	int space_remaining;
1642	NTSTATUS ntstatus = NT_STATUS_OK;
1643
1644	if (total_params < 12)
1645		return(ERROR_DOS(ERRDOS,ERRinvalidparam));
1646
1647	*mask = *directory = *resume_name = 0;
1648
1649	srvstr_get_path(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, True);
1650	if (!NT_STATUS_IS_OK(ntstatus)) {
1651		/* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1652		   complain (it thinks we're asking for the directory above the shared
1653		   path or an invalid name). Catch this as the resume name is only compared, never used in
1654		   a file access. JRA. */
1655		if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
1656			pstrcpy(resume_name, "..");
1657		} else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
1658			pstrcpy(resume_name, ".");
1659		} else {
1660			return ERROR_NT(ntstatus);
1661		}
1662	}
1663
1664	DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1665close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1666resume_key = %d resume name = %s continue=%d level = %d\n",
1667		dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
1668		requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1669
1670	if (!maxentries) {
1671		/* W2K3 seems to treat zero as 1. */
1672		maxentries = 1;
1673	}
1674
1675	switch (info_level) {
1676		case SMB_INFO_STANDARD:
1677		case SMB_INFO_QUERY_EA_SIZE:
1678		case SMB_FIND_FILE_DIRECTORY_INFO:
1679		case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1680		case SMB_FIND_FILE_NAMES_INFO:
1681		case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1682			break;
1683		case SMB_FIND_FILE_UNIX:
1684			if (!lp_unix_extensions())
1685				return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1686			break;
1687		default:
1688			return ERROR_DOS(ERRDOS,ERRunknownlevel);
1689	}
1690
1691	pdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1692	if(pdata == NULL)
1693		return ERROR_DOS(ERRDOS,ERRnomem);
1694
1695	*ppdata = pdata;
1696	memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1697
1698	/* Realloc the params space */
1699	params = SMB_REALLOC(*pparams, 6*SIZEOFWORD);
1700	if( params == NULL )
1701		return ERROR_DOS(ERRDOS,ERRnomem);
1702
1703	*pparams = params;
1704
1705	/* Check that the dptr is valid */
1706	if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num)))
1707		return ERROR_DOS(ERRDOS,ERRnofiles);
1708
1709	string_set(&conn->dirpath,dptr_path(dptr_num));
1710
1711	/* Get the wildcard mask from the dptr */
1712	if((p = dptr_wcard(dptr_num))== NULL) {
1713		DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1714		return ERROR_DOS(ERRDOS,ERRnofiles);
1715	}
1716
1717	pstrcpy(mask, p);
1718	pstrcpy(directory,conn->dirpath);
1719
1720	/* Get the attr mask from the dptr */
1721	dirtype = dptr_attr(dptr_num);
1722
1723	DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
1724		dptr_num, mask, dirtype,
1725		(long)conn->dirptr,
1726		dptr_TellDir(conn->dirptr)));
1727
1728	/* We don't need to check for VOL here as this is returned by
1729		a different TRANS2 call. */
1730
1731	DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
1732	if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1733		dont_descend = True;
1734
1735	p = pdata;
1736	space_remaining = max_data_bytes;
1737	out_of_space = False;
1738
1739	/*
1740	 * Seek to the correct position. We no longer use the resume key but
1741	 * depend on the last file name instead.
1742	 */
1743
1744	if(*resume_name && !continue_bit) {
1745		SMB_STRUCT_STAT st;
1746
1747		long current_pos = 0;
1748		/*
1749		 * Remember, mangle_map is called by
1750		 * get_lanman2_dir_entry(), so the resume name
1751		 * could be mangled. Ensure we check the unmangled name.
1752		 */
1753
1754		if (mangle_is_mangled(resume_name)) {
1755			mangle_check_cache(resume_name, sizeof(resume_name)-1);
1756		}
1757
1758		/*
1759		 * Fix for NT redirector problem triggered by resume key indexes
1760		 * changing between directory scans. We now return a resume key of 0
1761		 * and instead look for the filename to continue from (also given
1762		 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
1763		 * findfirst/findnext (as is usual) then the directory pointer
1764		 * should already be at the correct place.
1765		 */
1766
1767		finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
1768	} /* end if resume_name && !continue_bit */
1769
1770	for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
1771		BOOL got_exact_match = False;
1772
1773		/* this is a heuristic to avoid seeking the dirptr except when
1774			absolutely necessary. It allows for a filename of about 40 chars */
1775		if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1776			out_of_space = True;
1777			finished = False;
1778		} else {
1779			finished = !get_lanman2_dir_entry(conn,
1780						inbuf, outbuf,
1781						mask,dirtype,info_level,
1782						requires_resume_key,dont_descend,
1783						&p,pdata,space_remaining, &out_of_space, &got_exact_match,
1784						&last_entry_off);
1785		}
1786
1787		if (finished && out_of_space)
1788			finished = False;
1789
1790		if (!finished && !out_of_space)
1791			numentries++;
1792
1793		/*
1794		 * As an optimisation if we know we aren't looking
1795		 * for a wildcard name (ie. the name matches the wildcard exactly)
1796		 * then we can finish on any (first) match.
1797		 * This speeds up large directory searches. JRA.
1798		 */
1799
1800		if(got_exact_match)
1801			finished = True;
1802
1803		space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1804	}
1805
1806	/* Check if we can close the dirptr */
1807	if(close_after_request || (finished && close_if_end)) {
1808		DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
1809		dptr_close(&dptr_num); /* This frees up the saved mask */
1810	}
1811
1812	/* Set up the return parameter block */
1813	SSVAL(params,0,numentries);
1814	SSVAL(params,2,finished);
1815	SSVAL(params,4,0); /* Never an EA error */
1816	SSVAL(params,6,last_entry_off);
1817
1818	send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
1819
1820	if ((! *directory) && dptr_path(dptr_num))
1821		slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1822
1823	DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1824		smb_fn_name(CVAL(inbuf,smb_com)),
1825		mask, directory, dirtype, numentries ) );
1826
1827	return(-1);
1828}
1829
1830/****************************************************************************
1831 Reply to a TRANS2_QFSINFO (query filesystem info).
1832****************************************************************************/
1833
1834static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1835					char **pparams, int total_params, char **ppdata, int total_data,
1836					unsigned int max_data_bytes)
1837{
1838	char *pdata = *ppdata;
1839	char *params = *pparams;
1840	uint16 info_level = SVAL(params,0);
1841	int data_len, len;
1842	SMB_STRUCT_STAT st;
1843	char *vname = volume_label(SNUM(conn));
1844	int snum = SNUM(conn);
1845	char *fstype = lp_fstype(SNUM(conn));
1846	int quota_flag = 0;
1847
1848	DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
1849
1850	if(SMB_VFS_STAT(conn,".",&st)!=0) {
1851		DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
1852		return ERROR_DOS(ERRSRV,ERRinvdevice);
1853	}
1854
1855	pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1856	if ( pdata == NULL )
1857		return ERROR_DOS(ERRDOS,ERRnomem);
1858
1859	*ppdata = pdata;
1860	memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1861
1862	switch (info_level) {
1863		case SMB_INFO_ALLOCATION:
1864		{
1865			SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1866			data_len = 18;
1867			if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
1868				return(UNIXERROR(ERRHRD,ERRgeneral));
1869			}
1870
1871			block_size = lp_block_size(snum);
1872			if (bsize < block_size) {
1873				SMB_BIG_UINT factor = block_size/bsize;
1874				bsize = block_size;
1875				dsize /= factor;
1876				dfree /= factor;
1877			}
1878			if (bsize > block_size) {
1879				SMB_BIG_UINT factor = bsize/block_size;
1880				bsize = block_size;
1881				dsize *= factor;
1882				dfree *= factor;
1883			}
1884			bytes_per_sector = 512;
1885			sectors_per_unit = bsize/bytes_per_sector;
1886
1887			DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
1888cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
1889				(unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1890
1891			SIVAL(pdata,l1_idFileSystem,st.st_dev);
1892			SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
1893			SIVAL(pdata,l1_cUnit,dsize);
1894			SIVAL(pdata,l1_cUnitAvail,dfree);
1895			SSVAL(pdata,l1_cbSector,bytes_per_sector);
1896			break;
1897		}
1898
1899		case SMB_INFO_VOLUME:
1900			/* Return volume name */
1901			/*
1902			 * Add volume serial number - hash of a combination of
1903			 * the called hostname and the service name.
1904			 */
1905			SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
1906			len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN);
1907			SCVAL(pdata,l2_vol_cch,len);
1908			data_len = l2_vol_szVolLabel + len;
1909			DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
1910				(unsigned)st.st_ctime, len, vname));
1911			break;
1912
1913		case SMB_QUERY_FS_ATTRIBUTE_INFO:
1914		case SMB_FS_ATTRIBUTE_INFORMATION:
1915
1916
1917#if defined(HAVE_SYS_QUOTAS)
1918			quota_flag = FILE_VOLUME_QUOTAS;
1919#endif
1920
1921			SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
1922				(lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
1923				quota_flag); /* FS ATTRIBUTES */
1924
1925			SIVAL(pdata,4,255); /* Max filename component length */
1926			/* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
1927				and will think we can't do long filenames */
1928			len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
1929			SIVAL(pdata,8,len);
1930			data_len = 12 + len;
1931			break;
1932
1933		case SMB_QUERY_FS_LABEL_INFO:
1934		case SMB_FS_LABEL_INFORMATION:
1935			len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
1936			data_len = 4 + len;
1937			SIVAL(pdata,0,len);
1938			break;
1939
1940		case SMB_QUERY_FS_VOLUME_INFO:
1941		case SMB_FS_VOLUME_INFORMATION:
1942
1943			/*
1944			 * Add volume serial number - hash of a combination of
1945			 * the called hostname and the service name.
1946			 */
1947			SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
1948				(str_checksum(get_local_machine_name())<<16));
1949
1950			len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
1951			SIVAL(pdata,12,len);
1952			data_len = 18+len;
1953			DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
1954				(int)strlen(vname),vname, lp_servicename(snum)));
1955			break;
1956
1957		case SMB_QUERY_FS_SIZE_INFO:
1958		case SMB_FS_SIZE_INFORMATION:
1959		{
1960			SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1961			data_len = 24;
1962			if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
1963				return(UNIXERROR(ERRHRD,ERRgeneral));
1964			}
1965			block_size = lp_block_size(snum);
1966			if (bsize < block_size) {
1967				SMB_BIG_UINT factor = block_size/bsize;
1968				bsize = block_size;
1969				dsize /= factor;
1970				dfree /= factor;
1971			}
1972			if (bsize > block_size) {
1973				SMB_BIG_UINT factor = bsize/block_size;
1974				bsize = block_size;
1975				dsize *= factor;
1976				dfree *= factor;
1977			}
1978			bytes_per_sector = 512;
1979			sectors_per_unit = bsize/bytes_per_sector;
1980			DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
1981cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
1982				(unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
1983			SBIG_UINT(pdata,0,dsize);
1984			SBIG_UINT(pdata,8,dfree);
1985			SIVAL(pdata,16,sectors_per_unit);
1986			SIVAL(pdata,20,bytes_per_sector);
1987			break;
1988		}
1989
1990		case SMB_FS_FULL_SIZE_INFORMATION:
1991		{
1992			SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
1993			data_len = 32;
1994			if (SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
1995				return(UNIXERROR(ERRHRD,ERRgeneral));
1996			}
1997			block_size = lp_block_size(snum);
1998			if (bsize < block_size) {
1999				SMB_BIG_UINT factor = block_size/bsize;
2000				bsize = block_size;
2001				dsize /= factor;
2002				dfree /= factor;
2003			}
2004			if (bsize > block_size) {
2005				SMB_BIG_UINT factor = bsize/block_size;
2006				bsize = block_size;
2007				dsize *= factor;
2008				dfree *= factor;
2009			}
2010			bytes_per_sector = 512;
2011			sectors_per_unit = bsize/bytes_per_sector;
2012			DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2013cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2014				(unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2015			SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2016			SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2017			SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2018			SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2019			SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2020			break;
2021		}
2022
2023		case SMB_QUERY_FS_DEVICE_INFO:
2024		case SMB_FS_DEVICE_INFORMATION:
2025			data_len = 8;
2026			SIVAL(pdata,0,0); /* dev type */
2027			SIVAL(pdata,4,0); /* characteristics */
2028			break;
2029
2030#ifdef HAVE_SYS_QUOTAS
2031		case SMB_FS_QUOTA_INFORMATION:
2032		/*
2033		 * what we have to send --metze:
2034		 *
2035		 * Unknown1: 		24 NULL bytes
2036		 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2037		 * Hard Quota Limit:	8 bytes seems like SMB_BIG_UINT or so
2038		 * Quota Flags:		2 byte :
2039		 * Unknown3:		6 NULL bytes
2040		 *
2041		 * 48 bytes total
2042		 *
2043		 * details for Quota Flags:
2044		 *
2045		 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2046		 * 0x0010 Log Warn:  log if the user exceeds his Soft Quota
2047		 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2048		 * 0x0001 Enable Quotas: enable quota for this fs
2049		 *
2050		 */
2051		{
2052			/* we need to fake up a fsp here,
2053			 * because its not send in this call
2054			 */
2055			files_struct fsp;
2056			SMB_NTQUOTA_STRUCT quotas;
2057
2058			ZERO_STRUCT(fsp);
2059			ZERO_STRUCT(quotas);
2060
2061			fsp.conn = conn;
2062			fsp.fnum = -1;
2063			fsp.fd = -1;
2064
2065			/* access check */
2066			if (current_user.uid != 0) {
2067				DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2068					lp_servicename(SNUM(conn)),conn->user));
2069				return ERROR_DOS(ERRDOS,ERRnoaccess);
2070			}
2071
2072			if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2073				DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2074				return ERROR_DOS(ERRSRV,ERRerror);
2075			}
2076
2077			data_len = 48;
2078
2079			DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2080
2081			/* Unknown1 24 NULL bytes*/
2082			SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2083			SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2084			SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2085
2086			/* Default Soft Quota 8 bytes */
2087			SBIG_UINT(pdata,24,quotas.softlim);
2088
2089			/* Default Hard Quota 8 bytes */
2090			SBIG_UINT(pdata,32,quotas.hardlim);
2091
2092			/* Quota flag 2 bytes */
2093			SSVAL(pdata,40,quotas.qflags);
2094
2095			/* Unknown3 6 NULL bytes */
2096			SSVAL(pdata,42,0);
2097			SIVAL(pdata,44,0);
2098
2099			break;
2100		}
2101#endif /* HAVE_SYS_QUOTAS */
2102		case SMB_FS_OBJECTID_INFORMATION:
2103			data_len = 64;
2104			break;
2105
2106		/*
2107		 * Query the version and capabilities of the CIFS UNIX extensions
2108		 * in use.
2109		 */
2110
2111		case SMB_QUERY_CIFS_UNIX_INFO:
2112			if (!lp_unix_extensions())
2113				return ERROR_DOS(ERRDOS,ERRunknownlevel);
2114			data_len = 12;
2115			SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2116			SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2117			SBIG_UINT(pdata,4,((SMB_BIG_UINT)CIFS_UNIX_POSIX_ACLS_CAP)); /* We have POSIX ACLs. */
2118			break;
2119
2120		case SMB_MAC_QUERY_FS_INFO:
2121			/*
2122			 * Thursby MAC extension... ONLY on NTFS filesystems
2123			 * once we do streams then we don't need this
2124			 */
2125			if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2126				data_len = 88;
2127				SIVAL(pdata,84,0x100); /* Don't support mac... */
2128				break;
2129			}
2130			/* drop through */
2131		default:
2132			return ERROR_DOS(ERRDOS,ERRunknownlevel);
2133	}
2134
2135
2136	send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2137
2138	DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2139
2140	return -1;
2141}
2142
2143#ifdef HAVE_SYS_QUOTAS
2144/****************************************************************************
2145 Reply to a TRANS2_SETFSINFO (set filesystem info).
2146****************************************************************************/
2147
2148static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2149					char **pparams, int total_params, char **ppdata, int total_data,
2150					unsigned int max_data_bytes)
2151{
2152	char *pdata = *ppdata;
2153	char *params = *pparams;
2154	files_struct *fsp = NULL;
2155	uint16 info_level;
2156	int outsize;
2157	SMB_NTQUOTA_STRUCT quotas;
2158
2159	ZERO_STRUCT(quotas);
2160
2161	DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn))));
2162
2163	/* access check */
2164	if ((current_user.uid != 0)||!CAN_WRITE(conn)) {
2165		DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2166			lp_servicename(SNUM(conn)),conn->user));
2167		return ERROR_DOS(ERRSRV,ERRaccess);
2168	}
2169
2170	/*  */
2171	if (total_params < 4) {
2172		DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2173			total_params));
2174		return ERROR_DOS(ERRDOS,ERRinvalidparam);
2175	}
2176
2177	fsp = file_fsp(params,0);
2178
2179	if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2180		DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2181		return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2182	}
2183
2184	info_level = SVAL(params,2);
2185
2186	switch(info_level) {
2187		case SMB_FS_QUOTA_INFORMATION:
2188			/* note: normaly there're 48 bytes,
2189			 * but we didn't use the last 6 bytes for now
2190			 * --metze
2191			 */
2192			if (total_data < 42) {
2193				DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2194					total_data));
2195				return ERROR_DOS(ERRDOS,ERRunknownlevel);
2196			}
2197
2198			/* unknown_1 24 NULL bytes in pdata*/
2199
2200			/* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2201			quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2202#ifdef LARGE_SMB_OFF_T
2203			quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2204#else /* LARGE_SMB_OFF_T */
2205			if ((IVAL(pdata,28) != 0)&&
2206				((quotas.softlim != 0xFFFFFFFF)||
2207				(IVAL(pdata,28)!=0xFFFFFFFF))) {
2208				/* more than 32 bits? */
2209				return ERROR_DOS(ERRDOS,ERRunknownlevel);
2210			}
2211#endif /* LARGE_SMB_OFF_T */
2212
2213			/* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2214			quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2215#ifdef LARGE_SMB_OFF_T
2216			quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2217#else /* LARGE_SMB_OFF_T */
2218			if ((IVAL(pdata,36) != 0)&&
2219				((quotas.hardlim != 0xFFFFFFFF)||
2220				(IVAL(pdata,36)!=0xFFFFFFFF))) {
2221				/* more than 32 bits? */
2222				return ERROR_DOS(ERRDOS,ERRunknownlevel);
2223			}
2224#endif /* LARGE_SMB_OFF_T */
2225
2226			/* quota_flags 2 bytes **/
2227			quotas.qflags = SVAL(pdata,40);
2228
2229			/* unknown_2 6 NULL bytes follow*/
2230
2231			/* now set the quotas */
2232			if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2233				DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2234				return ERROR_DOS(ERRSRV,ERRerror);
2235			}
2236
2237			break;
2238		default:
2239			DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2240				info_level));
2241			return ERROR_DOS(ERRDOS,ERRunknownlevel);
2242			break;
2243	}
2244
2245	/*
2246	 * sending this reply works fine,
2247	 * but I'm not sure it's the same
2248	 * like windows do...
2249	 * --metze
2250	 */
2251	outsize = set_message(outbuf,10,0,True);
2252
2253	return outsize;
2254}
2255#endif /* HAVE_SYS_QUOTAS */
2256
2257/****************************************************************************
2258 Utility function to set bad path error.
2259****************************************************************************/
2260
2261int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2262{
2263	DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2264			err, (int)bad_path ));
2265
2266	if(err == ENOENT) {
2267		if (bad_path) {
2268			return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2269		} else {
2270			return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2271		}
2272	}
2273	return UNIXERROR(def_class,def_code);
2274}
2275
2276#if defined(HAVE_POSIX_ACLS)
2277/****************************************************************************
2278 Utility function to count the number of entries in a POSIX acl.
2279****************************************************************************/
2280
2281static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2282{
2283	unsigned int ace_count = 0;
2284	int entry_id = SMB_ACL_FIRST_ENTRY;
2285	SMB_ACL_ENTRY_T entry;
2286
2287	while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2288		/* get_next... */
2289		if (entry_id == SMB_ACL_FIRST_ENTRY) {
2290			entry_id = SMB_ACL_NEXT_ENTRY;
2291		}
2292		ace_count++;
2293	}
2294	return ace_count;
2295}
2296
2297/****************************************************************************
2298 Utility function to marshall a POSIX acl into wire format.
2299****************************************************************************/
2300
2301static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2302{
2303	int entry_id = SMB_ACL_FIRST_ENTRY;
2304	SMB_ACL_ENTRY_T entry;
2305
2306	while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2307		SMB_ACL_TAG_T tagtype;
2308		SMB_ACL_PERMSET_T permset;
2309		unsigned char perms = 0;
2310		unsigned int own_grp;
2311
2312		/* get_next... */
2313		if (entry_id == SMB_ACL_FIRST_ENTRY) {
2314			entry_id = SMB_ACL_NEXT_ENTRY;
2315		}
2316
2317		if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2318			DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2319			return False;
2320		}
2321
2322		if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2323			DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2324			return False;
2325		}
2326
2327		perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2328		perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2329		perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2330
2331		SCVAL(pdata,1,perms);
2332
2333		switch (tagtype) {
2334			case SMB_ACL_USER_OBJ:
2335				SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2336				own_grp = (unsigned int)pst->st_uid;
2337				SIVAL(pdata,2,own_grp);
2338				SIVAL(pdata,6,0);
2339				break;
2340			case SMB_ACL_USER:
2341				{
2342					uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2343					if (!puid) {
2344						DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2345					}
2346					own_grp = (unsigned int)*puid;
2347					SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2348					SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2349					SIVAL(pdata,2,own_grp);
2350					SIVAL(pdata,6,0);
2351					break;
2352				}
2353			case SMB_ACL_GROUP_OBJ:
2354				SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2355				own_grp = (unsigned int)pst->st_gid;
2356				SIVAL(pdata,2,own_grp);
2357				SIVAL(pdata,6,0);
2358				break;
2359			case SMB_ACL_GROUP:
2360				{
2361					gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2362					if (!pgid) {
2363						DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2364					}
2365					own_grp = (unsigned int)*pgid;
2366					SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2367					SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2368					SIVAL(pdata,2,own_grp);
2369					SIVAL(pdata,6,0);
2370					break;
2371				}
2372			case SMB_ACL_MASK:
2373				SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2374				SIVAL(pdata,2,0xFFFFFFFF);
2375				SIVAL(pdata,6,0xFFFFFFFF);
2376				break;
2377			case SMB_ACL_OTHER:
2378				SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2379				SIVAL(pdata,2,0xFFFFFFFF);
2380				SIVAL(pdata,6,0xFFFFFFFF);
2381				break;
2382			default:
2383				DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2384				return False;
2385		}
2386		pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2387	}
2388
2389	return True;
2390}
2391#endif
2392
2393/****************************************************************************
2394 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2395 file name or file id).
2396****************************************************************************/
2397
2398static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2399					char **pparams, int total_params, char **ppdata, int total_data,
2400					unsigned int max_data_bytes)
2401{
2402	char *params = *pparams;
2403	char *pdata = *ppdata;
2404	uint16 tran_call = SVAL(inbuf, smb_setup0);
2405	uint16 info_level;
2406	int mode=0;
2407	/* Foxconn modified start pling 12/15/2010 */
2408	/* SMB_OFF_T file_size=0; */
2409	SMB_BIG_UINT file_size = 0;
2410	/* Foxconn modified end pling 12/15/2010 */
2411	SMB_BIG_UINT allocation_size=0;
2412	unsigned int data_size;
2413	unsigned int param_size = 2;
2414	SMB_STRUCT_STAT sbuf;
2415	pstring fname, dos_fname;
2416	char *fullpathname;
2417	char *base_name;
2418	char *p;
2419	SMB_OFF_T pos = 0;
2420	BOOL bad_path = False;
2421	BOOL delete_pending = False;
2422	int len;
2423	time_t c_time;
2424	files_struct *fsp = NULL;
2425	uint32 desired_access = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2426
2427	if (!params)
2428		return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2429
2430	ZERO_STRUCT(sbuf);
2431
2432	if (tran_call == TRANSACT2_QFILEINFO) {
2433		if (total_params < 4)
2434			return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2435
2436		fsp = file_fsp(params,0);
2437		info_level = SVAL(params,2);
2438
2439		DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2440
2441		if(fsp && (fsp->fake_file_handle)) {
2442			/*
2443			 * This is actually for the QUOTA_FAKE_FILE --metze
2444			 */
2445
2446			pstrcpy(fname, fsp->fsp_name);
2447			/* We know this name is ok, it's already passed the checks. */
2448
2449		} else if(fsp && (fsp->is_directory || fsp->fd == -1)) {
2450			/*
2451			 * This is actually a QFILEINFO on a directory
2452			 * handle (returned from an NT SMB). NT5.0 seems
2453			 * to do this call. JRA.
2454			 */
2455			/* We know this name is ok, it's already passed the checks. */
2456			pstrcpy(fname, fsp->fsp_name);
2457
2458			if (INFO_LEVEL_IS_UNIX(info_level)) {
2459				/* Always do lstat for UNIX calls. */
2460				if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2461					DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2462					return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2463				}
2464			} else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2465				DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2466				return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2467			}
2468
2469			delete_pending = fsp->is_directory ? fsp->directory_delete_on_close : 0;
2470		} else {
2471			/*
2472			 * Original code - this is an open file.
2473			 */
2474			CHECK_FSP(fsp,conn);
2475
2476			pstrcpy(fname, fsp->fsp_name);
2477			if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) {
2478				DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2479				return(UNIXERROR(ERRDOS,ERRbadfid));
2480			}
2481			pos = fsp->position_information;
2482			delete_pending = fsp->delete_on_close;
2483			desired_access = fsp->desired_access;
2484		}
2485	} else {
2486		NTSTATUS status = NT_STATUS_OK;
2487
2488		/* qpathinfo */
2489		if (total_params < 6)
2490			return(ERROR_DOS(ERRDOS,ERRinvalidparam));
2491
2492		info_level = SVAL(params,0);
2493
2494		DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2495
2496		srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
2497		if (!NT_STATUS_IS_OK(status)) {
2498			return ERROR_NT(status);
2499		}
2500
2501		RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2502
2503		unix_convert(fname,conn,0,&bad_path,&sbuf);
2504		if (bad_path) {
2505			return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2506		}
2507		if (!check_name(fname,conn)) {
2508			DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2509			return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2510		}
2511
2512		if (INFO_LEVEL_IS_UNIX(info_level)) {
2513			/* Always do lstat for UNIX calls. */
2514			if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2515				DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2516				return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2517			}
2518		} else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2519			DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2520			return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2521		}
2522	}
2523
2524	if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2525		return ERROR_DOS(ERRDOS,ERRunknownlevel);
2526
2527	DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2528		fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2529
2530	p = strrchr_m(fname,'/');
2531	if (!p)
2532		base_name = fname;
2533	else
2534		base_name = p+1;
2535
2536	mode = dos_mode(conn,fname,&sbuf);
2537	if (!mode)
2538		mode = FILE_ATTRIBUTE_NORMAL;
2539
2540	fullpathname = fname;
2541	file_size = get_file_size(sbuf);
2542	allocation_size = get_allocation_size(conn,fsp,&sbuf);
2543	if (mode & aDIR) {
2544		/* This is necessary, as otherwise the desktop.ini file in
2545		 * this folder is ignored */
2546		mode |= (lp_profile_acls(SNUM(conn)) ? aRONLY : 0);
2547		file_size = 0;
2548	}
2549
2550	params = SMB_REALLOC(*pparams,2);
2551	if (params == NULL)
2552	  return ERROR_DOS(ERRDOS,ERRnomem);
2553	*pparams = params;
2554	memset((char *)params,'\0',2);
2555	data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
2556	pdata = SMB_REALLOC(*ppdata, data_size);
2557	if ( pdata == NULL )
2558		return ERROR_DOS(ERRDOS,ERRnomem);
2559	*ppdata = pdata;
2560
2561	if (total_data > 0 && IVAL(pdata,0) == total_data) {
2562		/* uggh, EAs for OS2 */
2563		DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data));
2564		return ERROR_DOS(ERRDOS,ERReasnotsupported);
2565	}
2566
2567	memset((char *)pdata,'\0',data_size);
2568
2569	c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2570
2571	if (fsp) {
2572		if (fsp->pending_modtime) {
2573			/* the pending modtime overrides the current modtime */
2574			sbuf.st_mtime = fsp->pending_modtime;
2575		}
2576	} else {
2577		/* Do we have this path open ? */
2578		files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
2579		if (fsp1 && fsp1->pending_modtime) {
2580			/* the pending modtime overrides the current modtime */
2581			sbuf.st_mtime = fsp1->pending_modtime;
2582		}
2583	}
2584
2585	if (lp_dos_filetime_resolution(SNUM(conn))) {
2586		c_time &= ~1;
2587		sbuf.st_atime &= ~1;
2588		sbuf.st_ctime &= ~1;
2589		sbuf.st_mtime &= ~1;
2590	}
2591
2592	/* NT expects the name to be in an exact form of the *full*
2593	   filename. See the trans2 torture test */
2594	if (strequal(base_name,".")) {
2595		pstrcpy(dos_fname, "\\");
2596	} else {
2597		pstr_sprintf(dos_fname, "\\%s", fname);
2598		string_replace(dos_fname, '/', '\\');
2599	}
2600
2601	switch (info_level) {
2602		case SMB_INFO_STANDARD:
2603			DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
2604			data_size = 22;
2605			put_dos_date2(pdata,l1_fdateCreation,c_time);
2606			put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2607			put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2608			SIVAL(pdata,l1_cbFile,(uint32)file_size);
2609			SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2610			SSVAL(pdata,l1_attrFile,mode);
2611			break;
2612
2613		case SMB_INFO_QUERY_EA_SIZE:
2614		{
2615			unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2616			DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
2617			data_size = 26;
2618			put_dos_date2(pdata,l1_fdateCreation,c_time);
2619			put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
2620			put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
2621			SIVAL(pdata,l1_cbFile,(uint32)file_size);
2622			SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
2623			SSVAL(pdata,l1_attrFile,mode);
2624			SIVAL(pdata,l1_attrFile+2,ea_size);
2625			break;
2626		}
2627
2628		case SMB_INFO_IS_NAME_VALID:
2629			DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
2630			if (tran_call == TRANSACT2_QFILEINFO) {
2631				/* os/2 needs this ? really ?*/
2632				return ERROR_DOS(ERRDOS,ERRbadfunc);
2633			}
2634			data_size = 0;
2635			param_size = 0;
2636			break;
2637
2638		case SMB_INFO_QUERY_EAS_FROM_LIST:
2639			DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
2640			data_size = 24;
2641			put_dos_date2(pdata,0,c_time);
2642			put_dos_date2(pdata,4,sbuf.st_atime);
2643			put_dos_date2(pdata,8,sbuf.st_mtime);
2644			SIVAL(pdata,12,(uint32)file_size);
2645			SIVAL(pdata,16,(uint32)allocation_size);
2646			SIVAL(pdata,20,mode);
2647			break;
2648
2649		case SMB_INFO_QUERY_ALL_EAS:
2650			DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
2651			/* We have data_size bytes to put EA's into. */
2652			data_size = fill_ea_buffer(pdata, data_size, conn, fsp, fname);
2653			break;
2654
2655		case SMB_FILE_BASIC_INFORMATION:
2656		case SMB_QUERY_FILE_BASIC_INFO:
2657
2658			if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
2659				DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
2660				data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
2661			} else {
2662				DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
2663				data_size = 40;
2664				SIVAL(pdata,36,0);
2665			}
2666			put_long_date(pdata,c_time);
2667			put_long_date(pdata+8,sbuf.st_atime);
2668			put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2669			put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2670			SIVAL(pdata,32,mode);
2671
2672			DEBUG(5,("SMB_QFBI - "));
2673			{
2674				time_t create_time = c_time;
2675				DEBUG(5,("create: %s ", ctime(&create_time)));
2676			}
2677			DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
2678			DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
2679			DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
2680			DEBUG(5,("mode: %x\n", mode));
2681
2682			break;
2683
2684		case SMB_FILE_STANDARD_INFORMATION:
2685		case SMB_QUERY_FILE_STANDARD_INFO:
2686
2687			DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
2688			data_size = 24;
2689			/* Foxconn modified start pling 03/11/2011 */
2690			/* Fix potential incorrect file size issue if file size > 4GB*/
2691#if 0
2692			SOFF_T(pdata,0,allocation_size);
2693			SOFF_T(pdata,8,file_size);
2694#endif
2695			SOFF64_T(pdata,0,allocation_size);
2696			SOFF64_T(pdata,8,file_size);
2697			/* Foxconn modified end pling 03/11/2011 */
2698			if (delete_pending & sbuf.st_nlink)
2699				SIVAL(pdata,16,sbuf.st_nlink - 1);
2700			else
2701				SIVAL(pdata,16,sbuf.st_nlink);
2702			SCVAL(pdata,20,0);
2703			SCVAL(pdata,21,(mode&aDIR)?1:0);
2704			break;
2705
2706		case SMB_FILE_EA_INFORMATION:
2707		case SMB_QUERY_FILE_EA_INFO:
2708		{
2709			unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2710			DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
2711			data_size = 4;
2712			SIVAL(pdata,0,ea_size);
2713			break;
2714		}
2715
2716		/* Get the 8.3 name - used if NT SMB was negotiated. */
2717		case SMB_QUERY_FILE_ALT_NAME_INFO:
2718		case SMB_FILE_ALTERNATE_NAME_INFORMATION:
2719		{
2720			pstring short_name;
2721
2722			DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
2723			pstrcpy(short_name,base_name);
2724			/* Mangle if not already 8.3 */
2725			if(!mangle_is_8_3(short_name, True)) {
2726				mangle_map(short_name,True,True,SNUM(conn));
2727			}
2728			len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
2729			data_size = 4 + len;
2730			SIVAL(pdata,0,len);
2731			break;
2732		}
2733
2734		case SMB_QUERY_FILE_NAME_INFO:
2735			/*
2736			  this must be *exactly* right for ACLs on mapped drives to work
2737			 */
2738			len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2739			DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
2740			data_size = 4 + len;
2741			SIVAL(pdata,0,len);
2742			break;
2743
2744		case SMB_FILE_ALLOCATION_INFORMATION:
2745		case SMB_QUERY_FILE_ALLOCATION_INFO:
2746			DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
2747			data_size = 8;
2748			/* Foxconn modified start pling 03/11/2011 */
2749			/* Fix potential incorrect file size issue if file size > 4GB*/
2750			/* SOFF_T(pdata,0,allocation_size); */
2751			SOFF64_T(pdata,0,allocation_size);
2752			/* Foxconn modified end pling 03/11/2011 */
2753			break;
2754
2755		case SMB_FILE_END_OF_FILE_INFORMATION:
2756		case SMB_QUERY_FILE_END_OF_FILEINFO:
2757			DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
2758			data_size = 8;
2759			/* Foxconn modified start pling 03/11/2011 */
2760			/* Fix potential incorrect file size issue if file size > 4GB.*/
2761			/* SOFF_T(pdata,0,file_size); */
2762			SOFF64_T(pdata,0,file_size);
2763			/* Foxconn modified end pling 03/11/2011 */
2764			break;
2765
2766		case SMB_QUERY_FILE_ALL_INFO:
2767		case SMB_FILE_ALL_INFORMATION:
2768		{
2769			unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
2770			DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
2771			put_long_date(pdata,c_time);
2772			put_long_date(pdata+8,sbuf.st_atime);
2773			put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2774			put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2775			SIVAL(pdata,32,mode);
2776			pdata += 40;
2777			/* Foxconn modified start pling 12/15/2010 */
2778			/* Fix Linux smb client can't see file > 4GB */
2779#if 0
2780			SOFF_T(pdata,0,allocation_size);
2781			SOFF_T(pdata,8,file_size);
2782#endif
2783			SOFF64_T(pdata,0,allocation_size);
2784			SOFF64_T(pdata,8,file_size);
2785			/* Foxconn modified end pling 12/15/2010 */
2786			if (delete_pending && sbuf.st_nlink)
2787				SIVAL(pdata,16,sbuf.st_nlink - 1);
2788			else
2789				SIVAL(pdata,16,sbuf.st_nlink);
2790			SCVAL(pdata,20,delete_pending);
2791			SCVAL(pdata,21,(mode&aDIR)?1:0);
2792			pdata += 24;
2793			SIVAL(pdata,0,ea_size);
2794			pdata += 4; /* EA info */
2795			len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
2796			SIVAL(pdata,0,len);
2797			pdata += 4 + len;
2798			data_size = PTR_DIFF(pdata,(*ppdata));
2799			break;
2800		}
2801		case SMB_FILE_INTERNAL_INFORMATION:
2802			/* This should be an index number - looks like
2803			   dev/ino to me :-)
2804
2805			   I think this causes us to fail the IFSKIT
2806			   BasicFileInformationTest. -tpot */
2807
2808			DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
2809			SIVAL(pdata,0,sbuf.st_dev);
2810			SIVAL(pdata,4,sbuf.st_ino);
2811			data_size = 8;
2812			break;
2813
2814		case SMB_FILE_ACCESS_INFORMATION:
2815			DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
2816			SIVAL(pdata,0,desired_access);
2817			data_size = 4;
2818			break;
2819
2820		case SMB_FILE_NAME_INFORMATION:
2821			/* Pathname with leading '\'. */
2822			{
2823				size_t byte_len;
2824				byte_len = dos_PutUniCode(pdata+4,dos_fname,max_data_bytes,False);
2825				DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
2826				SIVAL(pdata,0,byte_len);
2827				data_size = 4 + byte_len;
2828				break;
2829			}
2830
2831		case SMB_FILE_DISPOSITION_INFORMATION:
2832			DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
2833			data_size = 1;
2834			SCVAL(pdata,0,delete_pending);
2835			break;
2836
2837		case SMB_FILE_POSITION_INFORMATION:
2838			DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
2839			data_size = 8;
2840			SOFF_T(pdata,0,pos);
2841			break;
2842
2843		case SMB_FILE_MODE_INFORMATION:
2844			DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
2845			SIVAL(pdata,0,mode);
2846			data_size = 4;
2847			break;
2848
2849		case SMB_FILE_ALIGNMENT_INFORMATION:
2850			DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
2851			SIVAL(pdata,0,0); /* No alignment needed. */
2852			data_size = 4;
2853			break;
2854
2855#if 0
2856		/*
2857		 * NT4 server just returns "invalid query" to this - if we try to answer
2858		 * it then NTws gets a BSOD! (tridge).
2859		 * W2K seems to want this. JRA.
2860		 */
2861		case SMB_QUERY_FILE_STREAM_INFO:
2862#endif
2863		case SMB_FILE_STREAM_INFORMATION:
2864			DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
2865			if (mode & aDIR) {
2866				data_size = 0;
2867			} else {
2868				size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", 0xE, False);
2869				SIVAL(pdata,0,0); /* ??? */
2870				SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
2871				/* Foxconn modified start pling 03/11/2011 */
2872				/* Fix potential incorrect file size issue if file size > 4GB.*/
2873				/* SOFF_T(pdata,8,file_size); */
2874				SOFF64_T(pdata,8,file_size);
2875				/* Foxconn modified end pling 03/11/2011 */
2876				SIVAL(pdata,16,allocation_size);
2877				SIVAL(pdata,20,0); /* ??? */
2878				data_size = 24 + byte_len;
2879			}
2880			break;
2881
2882		case SMB_QUERY_COMPRESSION_INFO:
2883		case SMB_FILE_COMPRESSION_INFORMATION:
2884			DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
2885			/* Foxconn modified start pling 03/11/2011 */
2886			/* Fix potential incorrect file size issue if file size > 4GB.*/
2887			/* SOFF_T(pdata,0,file_size); */
2888			SOFF64_T(pdata,0,file_size);
2889			/* Foxconn modified end pling 03/11/2011 */
2890			SIVAL(pdata,8,0); /* ??? */
2891			SIVAL(pdata,12,0); /* ??? */
2892			data_size = 16;
2893			break;
2894
2895		case SMB_FILE_NETWORK_OPEN_INFORMATION:
2896			DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
2897			put_long_date(pdata,c_time);
2898			put_long_date(pdata+8,sbuf.st_atime);
2899			put_long_date(pdata+16,sbuf.st_mtime); /* write time */
2900			put_long_date(pdata+24,sbuf.st_mtime); /* change time */
2901			/* Foxconn modified start pling 03/11/2011 */
2902			/* Fix potential incorrect file size issue if file size > 4GB.*/
2903#if 0
2904			SIVAL(pdata,32,allocation_size);
2905			SOFF_T(pdata,40,file_size);
2906#endif
2907			SOFF64_T(pdata,32,allocation_size);
2908			SOFF64_T(pdata,40,file_size);
2909			/* Foxconn modified end pling 03/11/2011 */
2910			SIVAL(pdata,48,mode);
2911			SIVAL(pdata,52,0); /* ??? */
2912			data_size = 56;
2913			break;
2914
2915		case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
2916			DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
2917			SIVAL(pdata,0,mode);
2918			SIVAL(pdata,4,0);
2919			data_size = 8;
2920			break;
2921
2922		/*
2923		 * CIFS UNIX Extensions.
2924		 */
2925
2926		case SMB_QUERY_FILE_UNIX_BASIC:
2927
2928			DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
2929			DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
2930
2931			/* Foxconn modified start pling 03/11/2011 */
2932			/* Fix potential incorrect file size issue if file size > 4GB.*/
2933			/* SOFF_T(pdata,0,get_file_size(sbuf)); */             /* File size 64 Bit */
2934			SOFF64_T(pdata,0,get_file_size(sbuf));          /* File size 64 Bit */
2935			/* Foxconn modified end pling 03/11/2011 */
2936			pdata += 8;
2937
2938			/* Foxconn modified start pling 03/11/2011 */
2939			/* Fix potential incorrect file size issue if file size > 4GB.*/
2940			/* SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf));*/ /* Number of bytes used on disk - 64 Bit */
2941			SOFF64_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
2942			/* Foxconn modified end pling 03/11/2011 */
2943			pdata += 8;
2944
2945			put_long_date(pdata,sbuf.st_ctime);       /* Creation Time 64 Bit */
2946			put_long_date(pdata+8,sbuf.st_atime);     /* Last access time 64 Bit */
2947			put_long_date(pdata+16,sbuf.st_mtime);    /* Last modification time 64 Bit */
2948			pdata += 24;
2949
2950			SIVAL(pdata,0,sbuf.st_uid);               /* user id for the owner */
2951			SIVAL(pdata,4,0);
2952			pdata += 8;
2953
2954			SIVAL(pdata,0,sbuf.st_gid);               /* group id of owner */
2955			SIVAL(pdata,4,0);
2956			pdata += 8;
2957
2958			SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
2959			pdata += 4;
2960
2961			SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev));   /* Major device number if type is device */
2962			SIVAL(pdata,4,0);
2963			pdata += 8;
2964
2965			SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev));   /* Minor device number if type is device */
2966			SIVAL(pdata,4,0);
2967			pdata += 8;
2968
2969			SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino);   /* inode number */
2970			pdata += 8;
2971
2972			SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode));     /* Standard UNIX file permissions */
2973			SIVAL(pdata,4,0);
2974			pdata += 8;
2975
2976			SIVAL(pdata,0,sbuf.st_nlink);             /* number of hard links */
2977			SIVAL(pdata,4,0);
2978			pdata += 8+1;
2979			data_size = PTR_DIFF(pdata,(*ppdata));
2980
2981			{
2982				int i;
2983				DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
2984
2985				for (i=0; i<100; i++)
2986					DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
2987				DEBUG(4,("\n"));
2988			}
2989
2990			break;
2991
2992		case SMB_QUERY_FILE_UNIX_LINK:
2993			{
2994				pstring buffer;
2995
2996				DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
2997#ifdef S_ISLNK
2998				if(!S_ISLNK(sbuf.st_mode))
2999					return(UNIXERROR(ERRSRV,ERRbadlink));
3000#else
3001				return(UNIXERROR(ERRDOS,ERRbadlink));
3002#endif
3003				len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1);     /* read link */
3004				if (len == -1)
3005					return(UNIXERROR(ERRDOS,ERRnoaccess));
3006				buffer[len] = 0;
3007				len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3008				pdata += len;
3009				data_size = PTR_DIFF(pdata,(*ppdata));
3010
3011				break;
3012			}
3013
3014#if defined(HAVE_POSIX_ACLS)
3015		case SMB_QUERY_POSIX_ACL:
3016			{
3017				SMB_ACL_T file_acl = NULL;
3018				SMB_ACL_T def_acl = NULL;
3019				uint16 num_file_acls = 0;
3020				uint16 num_def_acls = 0;
3021
3022				if (fsp && !fsp->is_directory && (fsp->fd != -1)) {
3023					file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fd);
3024				} else {
3025					file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3026				}
3027
3028				if (file_acl == NULL && no_acl_syscall_error(errno)) {
3029					DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3030						fname ));
3031					return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3032				}
3033
3034				if (S_ISDIR(sbuf.st_mode)) {
3035					if (fsp && fsp->is_directory) {
3036						def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3037					} else {
3038						def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3039					}
3040					def_acl = free_empty_sys_acl(conn, def_acl);
3041				}
3042
3043				num_file_acls = count_acl_entries(conn, file_acl);
3044				num_def_acls = count_acl_entries(conn, def_acl);
3045
3046				if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3047					DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3048						data_size,
3049						(unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3050							SMB_POSIX_ACL_HEADER_SIZE) ));
3051					if (file_acl) {
3052						SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3053					}
3054					if (def_acl) {
3055						SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3056					}
3057					return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3058				}
3059
3060				SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3061				SSVAL(pdata,2,num_file_acls);
3062				SSVAL(pdata,4,num_def_acls);
3063				if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3064					if (file_acl) {
3065						SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3066					}
3067					if (def_acl) {
3068						SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3069					}
3070					return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3071				}
3072				if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3073					if (file_acl) {
3074						SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3075					}
3076					if (def_acl) {
3077						SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3078					}
3079					return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3080				}
3081
3082				if (file_acl) {
3083					SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3084				}
3085				if (def_acl) {
3086					SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3087				}
3088				data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3089				break;
3090			}
3091#endif
3092
3093		default:
3094			return ERROR_DOS(ERRDOS,ERRunknownlevel);
3095	}
3096
3097	send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
3098
3099	return(-1);
3100}
3101
3102/****************************************************************************
3103 Deal with the internal needs of setting the delete on close flag. Note that
3104 as the tdb locking is recursive, it is safe to call this from within
3105 open_file_shared. JRA.
3106****************************************************************************/
3107
3108NTSTATUS set_delete_on_close_internal(files_struct *fsp, BOOL delete_on_close, uint32 dosmode)
3109{
3110	if (delete_on_close) {
3111		/*
3112		 * Only allow delete on close for writable files.
3113		 */
3114
3115		if (!lp_delete_readonly(SNUM(fsp->conn))) {
3116			if (dosmode & aRONLY) {
3117				DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but file attribute is readonly.\n",
3118					fsp->fsp_name ));
3119				return NT_STATUS_CANNOT_DELETE;
3120			}
3121		}
3122
3123		/*
3124		 * Only allow delete on close for writable shares.
3125		 */
3126
3127		if (!CAN_WRITE(fsp->conn)) {
3128			DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but write access denied on share.\n",
3129				fsp->fsp_name ));
3130			return NT_STATUS_ACCESS_DENIED;
3131		}
3132
3133		/*
3134		 * Only allow delete on close for files/directories opened with delete intent.
3135		 */
3136
3137		if (!(fsp->desired_access & DELETE_ACCESS)) {
3138			DEBUG(10,("set_delete_on_close_internal: file %s delete on close flag set but delete access denied.\n",
3139				fsp->fsp_name ));
3140			return NT_STATUS_ACCESS_DENIED;
3141		}
3142	}
3143
3144	if(fsp->is_directory) {
3145		fsp->directory_delete_on_close = delete_on_close;
3146		DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, directory %s\n",
3147			delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3148	} else {
3149		fsp->delete_on_close = delete_on_close;
3150		DEBUG(10, ("set_delete_on_close_internal: %s delete on close flag for fnum = %d, file %s\n",
3151			delete_on_close ? "Added" : "Removed", fsp->fnum, fsp->fsp_name ));
3152	}
3153
3154	return NT_STATUS_OK;
3155}
3156
3157/****************************************************************************
3158 Sets the delete on close flag over all share modes on this file.
3159 Modify the share mode entry for all files open
3160 on this device and inode to tell other smbds we have
3161 changed the delete on close flag. This will be noticed
3162 in the close code, the last closer will delete the file
3163 if flag is set.
3164****************************************************************************/
3165
3166NTSTATUS set_delete_on_close_over_all(files_struct *fsp, BOOL delete_on_close)
3167{
3168	DEBUG(10,("set_delete_on_close_over_all: %s delete on close flag for fnum = %d, file %s\n",
3169		delete_on_close ? "Adding" : "Removing", fsp->fnum, fsp->fsp_name ));
3170
3171	if (fsp->is_directory || fsp->is_stat)
3172		return NT_STATUS_OK;
3173
3174	if (lock_share_entry_fsp(fsp) == False)
3175		return NT_STATUS_ACCESS_DENIED;
3176
3177	if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
3178		DEBUG(0,("set_delete_on_close_over_all: failed to change delete on close flag for file %s\n",
3179			fsp->fsp_name ));
3180		unlock_share_entry_fsp(fsp);
3181		return NT_STATUS_ACCESS_DENIED;
3182	}
3183
3184	unlock_share_entry_fsp(fsp);
3185	return NT_STATUS_OK;
3186}
3187
3188/****************************************************************************
3189 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3190 code.
3191****************************************************************************/
3192
3193NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
3194{
3195	BOOL bad_path_oldname = False;
3196	BOOL bad_path_newname = False;
3197	SMB_STRUCT_STAT sbuf1, sbuf2;
3198	pstring last_component_oldname;
3199	pstring last_component_newname;
3200	NTSTATUS status = NT_STATUS_OK;
3201
3202	ZERO_STRUCT(sbuf1);
3203	ZERO_STRUCT(sbuf2);
3204
3205	/* No wildcards. */
3206	if (ms_has_wild(newname) || ms_has_wild(oldname)) {
3207		return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
3208	}
3209
3210	unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
3211	if (bad_path_oldname) {
3212		return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3213	}
3214
3215	/* Quick check for "." and ".." */
3216	if (last_component_oldname[0] == '.') {
3217		if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
3218			return NT_STATUS_OBJECT_NAME_INVALID;
3219		}
3220	}
3221
3222	/* source must already exist. */
3223	if (!VALID_STAT(sbuf1)) {
3224		return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3225	}
3226
3227	if (!check_name(oldname,conn)) {
3228		return NT_STATUS_ACCESS_DENIED;
3229	}
3230
3231	unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
3232	if (bad_path_newname) {
3233		return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3234	}
3235
3236	/* Quick check for "." and ".." */
3237	if (last_component_newname[0] == '.') {
3238		if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
3239			return NT_STATUS_OBJECT_NAME_INVALID;
3240		}
3241	}
3242
3243	/* Disallow if newname already exists. */
3244	if (VALID_STAT(sbuf2)) {
3245		return NT_STATUS_OBJECT_NAME_COLLISION;
3246	}
3247
3248	if (!check_name(newname,conn)) {
3249		return NT_STATUS_ACCESS_DENIED;
3250	}
3251
3252	/* No links from a directory. */
3253	if (S_ISDIR(sbuf1.st_mode)) {
3254		return NT_STATUS_FILE_IS_A_DIRECTORY;
3255	}
3256
3257	/* Ensure this is within the share. */
3258	if (!reduce_name(conn, oldname) != 0)
3259		return NT_STATUS_ACCESS_DENIED;
3260
3261	DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3262
3263	if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3264		status = map_nt_error_from_unix(errno);
3265		DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3266                                nt_errstr(status), newname, oldname));
3267	}
3268
3269	return status;
3270}
3271
3272/****************************************************************************
3273 Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3274****************************************************************************/
3275
3276static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3277					char **pparams, int total_params, char **ppdata, int total_data,
3278					unsigned int max_data_bytes)
3279{
3280	char *params = *pparams;
3281	char *pdata = *ppdata;
3282	uint16 tran_call = SVAL(inbuf, smb_setup0);
3283	uint16 info_level;
3284	int dosmode=0;
3285    /* Foxconn modified start pling 11/19/2009 */
3286	//SMB_OFF_T size=0;
3287	SMB_BIG_UINT size=0;
3288    /* Foxconn modified end pling 11/19/2009 */
3289	struct utimbuf tvs;
3290	SMB_STRUCT_STAT sbuf;
3291	pstring fname;
3292	int fd = -1;
3293	BOOL bad_path = False;
3294	files_struct *fsp = NULL;
3295	uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3296	gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3297	mode_t unixmode = 0;
3298	NTSTATUS status = NT_STATUS_OK;
3299
3300	if (!params)
3301		return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3302
3303	ZERO_STRUCT(sbuf);
3304
3305	if (tran_call == TRANSACT2_SETFILEINFO) {
3306		if (total_params < 4)
3307			return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3308
3309		fsp = file_fsp(params,0);
3310		info_level = SVAL(params,2);
3311
3312		if(fsp && (fsp->is_directory || fsp->fd == -1)) {
3313			/*
3314			 * This is actually a SETFILEINFO on a directory
3315			 * handle (returned from an NT SMB). NT5.0 seems
3316			 * to do this call. JRA.
3317			 */
3318			pstrcpy(fname, fsp->fsp_name);
3319			if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3320				DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3321				return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3322			}
3323		} else if (fsp && fsp->print_file) {
3324			/*
3325			 * Doing a DELETE_ON_CLOSE should cancel a print job.
3326			 */
3327			if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3328				fsp->share_mode = FILE_DELETE_ON_CLOSE;
3329
3330				DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3331
3332				SSVAL(params,0,0);
3333				send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3334				return(-1);
3335			} else
3336				return (UNIXERROR(ERRDOS,ERRbadpath));
3337	    } else {
3338			/*
3339			 * Original code - this is an open file.
3340			 */
3341			CHECK_FSP(fsp,conn);
3342
3343			pstrcpy(fname, fsp->fsp_name);
3344			fd = fsp->fd;
3345
3346			if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3347				DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3348				return(UNIXERROR(ERRDOS,ERRbadfid));
3349			}
3350		}
3351	} else {
3352		/* set path info */
3353		if (total_params < 6)
3354			return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3355
3356		info_level = SVAL(params,0);
3357		srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status, False);
3358		if (!NT_STATUS_IS_OK(status)) {
3359			return ERROR_NT(status);
3360		}
3361		unix_convert(fname,conn,0,&bad_path,&sbuf);
3362		if (bad_path) {
3363			return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3364		}
3365
3366		/*
3367		 * For CIFS UNIX extensions the target name may not exist.
3368		 */
3369
3370		if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3371			DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3372			return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3373		}
3374
3375		if(!check_name(fname, conn)) {
3376			return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3377		}
3378
3379	}
3380
3381	if (!CAN_WRITE(conn))
3382		return ERROR_DOS(ERRSRV,ERRaccess);
3383
3384	if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3385		return ERROR_DOS(ERRDOS,ERRunknownlevel);
3386
3387	if (VALID_STAT(sbuf))
3388		unixmode = sbuf.st_mode;
3389
3390	DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3391		tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3392
3393	/* Realloc the parameter and data sizes */
3394	params = SMB_REALLOC(*pparams,2);
3395	if(params == NULL)
3396		return ERROR_DOS(ERRDOS,ERRnomem);
3397	*pparams = params;
3398
3399	SSVAL(params,0,0);
3400
3401	if (fsp && fsp->pending_modtime) {
3402		/* the pending modtime overrides the current modtime */
3403		sbuf.st_mtime = fsp->pending_modtime;
3404	}
3405
3406	size = get_file_size(sbuf);
3407	tvs.modtime = sbuf.st_mtime;
3408	tvs.actime = sbuf.st_atime;
3409	dosmode = dos_mode(conn,fname,&sbuf);
3410	unixmode = sbuf.st_mode;
3411
3412	set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3413	set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3414
3415	switch (info_level) {
3416		case SMB_INFO_STANDARD:
3417		{
3418			if (total_data < 12)
3419				return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3420
3421			/* access time */
3422			tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
3423			/* write time */
3424			tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
3425			break;
3426		}
3427
3428		case SMB_INFO_SET_EA:
3429			status = set_ea(conn, fsp, fname, pdata, total_data);
3430			if (NT_STATUS_V(status) !=  NT_STATUS_V(NT_STATUS_OK))
3431				return ERROR_NT(status);
3432			break;
3433
3434		/* XXXX um, i don't think this is right.
3435			it's also not in the cifs6.txt spec.
3436		*/
3437		case SMB_INFO_QUERY_EAS_FROM_LIST:
3438			if (total_data < 28)
3439				return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3440
3441			tvs.actime = make_unix_date2(pdata+8);
3442			tvs.modtime = make_unix_date2(pdata+12);
3443			size = IVAL(pdata,16);
3444			dosmode = IVAL(pdata,24);
3445			break;
3446
3447		/* XXXX nor this.  not in cifs6.txt, either. */
3448		case SMB_INFO_QUERY_ALL_EAS:
3449			if (total_data < 28)
3450				return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3451
3452			tvs.actime = make_unix_date2(pdata+8);
3453			tvs.modtime = make_unix_date2(pdata+12);
3454			size = IVAL(pdata,16);
3455			dosmode = IVAL(pdata,24);
3456			break;
3457
3458		case SMB_SET_FILE_BASIC_INFO:
3459		case SMB_FILE_BASIC_INFORMATION:
3460		{
3461			/* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3462			time_t write_time;
3463			time_t changed_time;
3464
3465			if (total_data < 36)
3466				return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3467
3468			/* Ignore create time at offset pdata. */
3469
3470			/* access time */
3471			tvs.actime = interpret_long_date(pdata+8);
3472
3473			write_time = interpret_long_date(pdata+16);
3474			changed_time = interpret_long_date(pdata+24);
3475
3476			tvs.modtime = MIN(write_time, changed_time);
3477
3478			if (write_time > tvs.modtime && write_time != (time_t)-1) {
3479				tvs.modtime = write_time;
3480			}
3481			/* Prefer a defined time to an undefined one. */
3482			if (null_mtime(tvs.modtime)) {
3483				tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
3484			}
3485
3486			/* attributes */
3487			dosmode = IVAL(pdata,32);
3488			break;
3489		}
3490
3491		case SMB_FILE_ALLOCATION_INFORMATION:
3492		case SMB_SET_FILE_ALLOCATION_INFO:
3493		{
3494			int ret = -1;
3495			SMB_BIG_UINT allocation_size;
3496
3497			if (total_data < 8)
3498				return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3499
3500			allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3501#ifdef LARGE_SMB_OFF_T
3502			allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3503#else /* LARGE_SMB_OFF_T */
3504			/* Foxconn modified start pling 03/11/2011 */
3505#if 0
3506			if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3507				return ERROR_DOS(ERRDOS,ERRunknownlevel);
3508#endif
3509			if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3510				allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3511			/* Foxconn modified end pling 03/11/2011 */
3512#endif /* LARGE_SMB_OFF_T */
3513			DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3514					fname, (double)allocation_size ));
3515
3516			if (allocation_size) {
3517				allocation_size = smb_roundup(conn, allocation_size);
3518			}
3519
3520			if(allocation_size != get_file_size(sbuf)) {
3521				SMB_STRUCT_STAT new_sbuf;
3522
3523				DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3524					fname, (double)allocation_size ));
3525
3526				if (fd == -1) {
3527					files_struct *new_fsp = NULL;
3528					int access_mode = 0;
3529					int action = 0;
3530
3531					if(global_oplock_break) {
3532						/* Queue this file modify as we are the process of an oplock break.  */
3533
3534						DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
3535						DEBUGADD(2,( "in oplock break state.\n"));
3536
3537						push_oplock_pending_smb_message(inbuf, length);
3538						return -1;
3539					}
3540
3541					new_fsp = open_file_shared1(conn, fname, &sbuf,FILE_WRITE_DATA,
3542									SET_OPEN_MODE(DOS_OPEN_RDWR),
3543									(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
3544									FILE_ATTRIBUTE_NORMAL,
3545									INTERNAL_OPEN_ONLY, &access_mode, &action);
3546
3547					if (new_fsp == NULL)
3548						return(UNIXERROR(ERRDOS,ERRbadpath));
3549					ret = vfs_allocate_file_space(new_fsp, allocation_size);
3550					if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) {
3551						DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3552									new_fsp->fnum, strerror(errno)));
3553						ret = -1;
3554					}
3555					close_file(new_fsp,True);
3556				} else {
3557					ret = vfs_allocate_file_space(fsp, allocation_size);
3558					if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3559						DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3560									fsp->fnum, strerror(errno)));
3561						ret = -1;
3562					}
3563				}
3564				if (ret == -1)
3565					return ERROR_NT(NT_STATUS_DISK_FULL);
3566
3567				/* Allocate can truncate size... */
3568				size = get_file_size(new_sbuf);
3569			}
3570
3571			break;
3572		}
3573
3574		case SMB_FILE_END_OF_FILE_INFORMATION:
3575		case SMB_SET_FILE_END_OF_FILE_INFO:
3576		{
3577			if (total_data < 8)
3578				return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3579
3580			size = IVAL(pdata,0);
3581#ifdef LARGE_SMB_OFF_T
3582			size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3583#else /* LARGE_SMB_OFF_T */
3584            /* Foxconn modified start pling 11/19/2009 */
3585            /* We should support large file size */
3586#if 0
3587			if (IVAL(pdata,4) != 0)	/* more than 32 bits? */
3588				return ERROR_DOS(ERRDOS,ERRunknownlevel);
3589#endif
3590			if (IVAL(pdata,4) != 0)	{ /* more than 32 bits? */
3591			    size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3592            }
3593            /* Foxconn modified end pling 11/19/2009 */
3594#endif /* LARGE_SMB_OFF_T */
3595			DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3596			break;
3597		}
3598
3599		case SMB_FILE_DISPOSITION_INFORMATION:
3600		case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3601		{
3602			BOOL delete_on_close;
3603
3604			if (total_data < 1)
3605				return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3606
3607			delete_on_close = (CVAL(pdata,0) ? True : False);
3608
3609			/* Just ignore this set on a path. */
3610			if (tran_call != TRANSACT2_SETFILEINFO)
3611				break;
3612
3613			if (fsp == NULL)
3614				return(UNIXERROR(ERRDOS,ERRbadfid));
3615
3616			status = set_delete_on_close_internal(fsp, delete_on_close, dosmode);
3617
3618			if (NT_STATUS_V(status) !=  NT_STATUS_V(NT_STATUS_OK))
3619				return ERROR_NT(status);
3620
3621			/* The set is across all open files on this dev/inode pair. */
3622			status =set_delete_on_close_over_all(fsp, delete_on_close);
3623			if (NT_STATUS_V(status) !=  NT_STATUS_V(NT_STATUS_OK))
3624				return ERROR_NT(status);
3625
3626			break;
3627		}
3628
3629		case SMB_FILE_POSITION_INFORMATION:
3630		{
3631			SMB_BIG_UINT position_information;
3632
3633			if (total_data < 8)
3634				return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3635
3636			position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3637#ifdef LARGE_SMB_OFF_T
3638			position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3639#else /* LARGE_SMB_OFF_T */
3640			/* Foxconn modified start pling 03/11/2011 */
3641			/* Fix potential incorrect file size issue if file size > 4GB */
3642#if 0
3643			if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3644				return ERROR_DOS(ERRDOS,ERRunknownlevel);
3645#endif
3646			if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3647				position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3648			/* Foxconn modified end pling 03/11/2011 */
3649#endif /* LARGE_SMB_OFF_T */
3650			DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
3651					fname, (double)position_information ));
3652			if (fsp)
3653				fsp->position_information = position_information;
3654			break;
3655		}
3656
3657		/*
3658		 * CIFS UNIX extensions.
3659		 */
3660
3661		case SMB_SET_FILE_UNIX_BASIC:
3662		{
3663			uint32 raw_unixmode;
3664
3665			if (total_data < 100)
3666				return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3667
3668			if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
3669			   IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
3670				size=IVAL(pdata,0); /* first 8 Bytes are size */
3671#ifdef LARGE_SMB_OFF_T
3672				size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3673#else /* LARGE_SMB_OFF_T */
3674				/* Foxconn modified start pling 03/11/2011 */
3675				/* Fix potential incorrect file size issue if file size > 4GB */
3676#if 0
3677				if (IVAL(pdata,4) != 0)	/* more than 32 bits? */
3678					return ERROR_DOS(ERRDOS,ERRunknownlevel);
3679#endif
3680				if (IVAL(pdata,4) != 0)	/* more than 32 bits? */
3681					size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3682				/* Foxconn modified end pling 03/11/2011 */
3683#endif /* LARGE_SMB_OFF_T */
3684			}
3685			pdata+=24;          /* ctime & st_blocks are not changed */
3686			tvs.actime = interpret_long_date(pdata); /* access_time */
3687			tvs.modtime = interpret_long_date(pdata+8); /* modification_time */
3688			pdata+=16;
3689			set_owner = (uid_t)IVAL(pdata,0);
3690			pdata += 8;
3691			set_grp = (gid_t)IVAL(pdata,0);
3692			pdata += 8;
3693			raw_unixmode = IVAL(pdata,28);
3694			unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
3695			dosmode = 0; /* Ensure dos mode change doesn't override this. */
3696
3697			DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
3698size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
3699				fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
3700
3701			if (!VALID_STAT(sbuf)) {
3702
3703				/*
3704				 * The only valid use of this is to create character and block
3705				 * devices, and named pipes. This is deprecated (IMHO) and
3706				 * a new info level should be used for mknod. JRA.
3707				 */
3708
3709				uint32 file_type = IVAL(pdata,0);
3710#if defined(HAVE_MAKEDEV)
3711				uint32 dev_major = IVAL(pdata,4);
3712				uint32 dev_minor = IVAL(pdata,12);
3713#endif
3714
3715				uid_t myuid = geteuid();
3716				gid_t mygid = getegid();
3717				SMB_DEV_T dev = (SMB_DEV_T)0;
3718
3719				if (tran_call == TRANSACT2_SETFILEINFO)
3720					return(ERROR_DOS(ERRDOS,ERRnoaccess));
3721
3722				if (raw_unixmode == SMB_MODE_NO_CHANGE)
3723					return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3724
3725#if defined(HAVE_MAKEDEV)
3726				dev = makedev(dev_major, dev_minor);
3727#endif
3728
3729				/* We can only create as the owner/group we are. */
3730
3731				if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
3732					return(ERROR_DOS(ERRDOS,ERRnoaccess));
3733				if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
3734					return(ERROR_DOS(ERRDOS,ERRnoaccess));
3735
3736				switch (file_type) {
3737#if defined(S_IFIFO)
3738					case UNIX_TYPE_FIFO:
3739						unixmode |= S_IFIFO;
3740						break;
3741#endif
3742#if defined(S_IFSOCK)
3743					case UNIX_TYPE_SOCKET:
3744						unixmode |= S_IFSOCK;
3745						break;
3746#endif
3747#if defined(S_IFCHR)
3748					case UNIX_TYPE_CHARDEV:
3749						unixmode |= S_IFCHR;
3750						break;
3751#endif
3752#if defined(S_IFBLK)
3753					case UNIX_TYPE_BLKDEV:
3754						unixmode |= S_IFBLK;
3755						break;
3756#endif
3757					default:
3758						return(ERROR_DOS(ERRDOS,ERRnoaccess));
3759				}
3760
3761				DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
37620%o for file %s\n", (double)dev, unixmode, fname ));
3763
3764				/* Ok - do the mknod. */
3765				if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
3766					return(UNIXERROR(ERRDOS,ERRnoaccess));
3767
3768				inherit_access_acl(conn, fname, unixmode);
3769
3770				SSVAL(params,0,0);
3771				send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3772				return(-1);
3773			}
3774
3775			/*
3776			 * Deal with the UNIX specific mode set.
3777			 */
3778
3779			if (raw_unixmode != SMB_MODE_NO_CHANGE) {
3780				DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
3781					(unsigned int)unixmode, fname ));
3782				if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
3783					return(UNIXERROR(ERRDOS,ERRnoaccess));
3784			}
3785
3786			/*
3787			 * Deal with the UNIX specific uid set.
3788			 */
3789
3790			if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
3791				DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
3792					(unsigned int)set_owner, fname ));
3793				if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
3794					return(UNIXERROR(ERRDOS,ERRnoaccess));
3795			}
3796
3797			/*
3798			 * Deal with the UNIX specific gid set.
3799			 */
3800
3801			if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
3802				DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
3803					(unsigned int)set_owner, fname ));
3804				if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
3805					return(UNIXERROR(ERRDOS,ERRnoaccess));
3806			}
3807			break;
3808		}
3809
3810		case SMB_SET_FILE_UNIX_LINK:
3811		{
3812			pstring link_target;
3813			char *newname = fname;
3814
3815			/* Set a symbolic link. */
3816			/* Don't allow this if follow links is false. */
3817
3818			if (!lp_symlinks(SNUM(conn)))
3819				return(ERROR_DOS(ERRDOS,ERRnoaccess));
3820
3821			srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
3822
3823			/* !widelinks forces the target path to be within the share. */
3824			/* This means we can interpret the target as a pathname. */
3825			if (!lp_widelinks(SNUM(conn))) {
3826				pstring rel_name;
3827				char *last_dirp = NULL;
3828
3829				unix_format(link_target);
3830				if (*link_target == '/') {
3831					/* No absolute paths allowed. */
3832					return(UNIXERROR(ERRDOS,ERRnoaccess));
3833				}
3834				pstrcpy(rel_name, newname);
3835				last_dirp = strrchr_m(rel_name, '/');
3836				if (last_dirp) {
3837					last_dirp[1] = '\0';
3838				} else {
3839					pstrcpy(rel_name, "./");
3840				}
3841				pstrcat(rel_name, link_target);
3842
3843				if (!check_name(rel_name, conn)) {
3844					return(UNIXERROR(ERRDOS,ERRnoaccess));
3845				}
3846			}
3847
3848			DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
3849				fname, link_target ));
3850
3851			if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
3852				return(UNIXERROR(ERRDOS,ERRnoaccess));
3853			SSVAL(params,0,0);
3854			send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3855			return(-1);
3856		}
3857
3858		case SMB_SET_FILE_UNIX_HLINK:
3859		{
3860			pstring oldname;
3861			char *newname = fname;
3862
3863			/* Set a hard link. */
3864			srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status, False);
3865			if (!NT_STATUS_IS_OK(status)) {
3866				return ERROR_NT(status);
3867			}
3868
3869			DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
3870				fname, oldname));
3871
3872			status = hardlink_internals(conn, oldname, newname);
3873			if (!NT_STATUS_IS_OK(status)) {
3874				return ERROR_NT(status);
3875			}
3876
3877			SSVAL(params,0,0);
3878			send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3879			return(-1);
3880		}
3881
3882		case SMB_FILE_RENAME_INFORMATION:
3883		{
3884			BOOL overwrite;
3885			uint32 root_fid;
3886			uint32 len;
3887			pstring newname;
3888			pstring base_name;
3889			char *p;
3890
3891			if (total_data < 12)
3892				return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3893
3894			overwrite = (CVAL(pdata,0) ? True : False);
3895			root_fid = IVAL(pdata,4);
3896			len = IVAL(pdata,8);
3897			srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, False);
3898			if (!NT_STATUS_IS_OK(status)) {
3899				return ERROR_NT(status);
3900			}
3901
3902			/* Check the new name has no '/' characters. */
3903			if (strchr_m(newname, '/'))
3904				return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
3905
3906			RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3907
3908			/* Create the base directory. */
3909			pstrcpy(base_name, fname);
3910			p = strrchr_m(base_name, '/');
3911			if (p)
3912				*p = '\0';
3913			/* Append the new name. */
3914			pstrcat(base_name, "/");
3915			pstrcat(base_name, newname);
3916
3917			if (fsp) {
3918				DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
3919					fsp->fnum, fsp->fsp_name, base_name ));
3920				status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
3921			} else {
3922				DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
3923					fname, newname ));
3924				status = rename_internals(conn, fname, base_name, 0, overwrite);
3925			}
3926			if (!NT_STATUS_IS_OK(status)) {
3927				return ERROR_NT(status);
3928			}
3929			process_pending_change_notify_queue((time_t)0);
3930			SSVAL(params,0,0);
3931			send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3932			return(-1);
3933		}
3934
3935#if defined(HAVE_POSIX_ACLS)
3936		case SMB_SET_POSIX_ACL:
3937		{
3938			uint16 posix_acl_version;
3939			uint16 num_file_acls;
3940			uint16 num_def_acls;
3941			BOOL valid_file_acls = True;
3942			BOOL valid_def_acls = True;
3943
3944			if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
3945				return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3946			}
3947			posix_acl_version = SVAL(pdata,0);
3948			num_file_acls = SVAL(pdata,2);
3949			num_def_acls = SVAL(pdata,4);
3950
3951			if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
3952				valid_file_acls = False;
3953				num_file_acls = 0;
3954			}
3955
3956			if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
3957				valid_def_acls = False;
3958				num_def_acls = 0;
3959			}
3960
3961			if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
3962				return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3963			}
3964
3965			if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
3966					(num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
3967				return(ERROR_DOS(ERRDOS,ERRinvalidparam));
3968			}
3969
3970			if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
3971					pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
3972				return(UNIXERROR(ERRDOS,ERRnoaccess));
3973			}
3974
3975			if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
3976					pdata + SMB_POSIX_ACL_HEADER_SIZE +
3977					(num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
3978				return(UNIXERROR(ERRDOS,ERRnoaccess));
3979			}
3980
3981			SSVAL(params,0,0);
3982			send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3983			return(-1);
3984		}
3985#endif
3986
3987		default:
3988			return ERROR_DOS(ERRDOS,ERRunknownlevel);
3989	}
3990
3991	/* get some defaults (no modifications) if any info is zero or -1. */
3992	if (null_mtime(tvs.actime)) {
3993		tvs.actime = sbuf.st_atime;
3994	}
3995
3996	if (null_mtime(tvs.modtime)) {
3997		tvs.modtime = sbuf.st_mtime;
3998	}
3999
4000	DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
4001	DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
4002	DEBUG(6,("size: %.0f ", (double)size));
4003
4004	if (dosmode) {
4005		if (S_ISDIR(sbuf.st_mode))
4006			dosmode |= aDIR;
4007		else
4008			dosmode &= ~aDIR;
4009	}
4010
4011	DEBUG(6,("dosmode: %x\n"  , dosmode));
4012
4013	if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
4014		(info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
4015		(info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
4016		(info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
4017
4018		/*
4019		 * Only do this test if we are not explicitly
4020		 * changing the size of a file.
4021		 */
4022		if (!size)
4023			size = get_file_size(sbuf);
4024	}
4025
4026	/*
4027	 * Try and set the times, size and mode of this file -
4028	 * if they are different from the current values
4029	 */
4030
4031	/* check the mode isn't different, before changing it */
4032	if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
4033
4034		DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
4035
4036		if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
4037			DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
4038			return(UNIXERROR(ERRDOS,ERRnoaccess));
4039		}
4040	}
4041
4042	/* Now the size. */
4043	if (size != get_file_size(sbuf)) {
4044
4045		int ret;
4046
4047		DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
4048			fname, (double)size ));
4049
4050		if (fd == -1) {
4051			files_struct *new_fsp = NULL;
4052			int access_mode = 0;
4053			int action = 0;
4054
4055			if(global_oplock_break) {
4056				/* Queue this file modify as we are the process of an oplock break.  */
4057
4058				DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
4059				DEBUGADD(2,( "in oplock break state.\n"));
4060
4061				push_oplock_pending_smb_message(inbuf, length);
4062				return -1;
4063			}
4064
4065			new_fsp = open_file_shared(conn, fname, &sbuf,
4066						SET_OPEN_MODE(DOS_OPEN_RDWR),
4067						(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
4068						FILE_ATTRIBUTE_NORMAL,
4069						INTERNAL_OPEN_ONLY, &access_mode, &action);
4070
4071			if (new_fsp == NULL)
4072				return(UNIXERROR(ERRDOS,ERRbadpath));
4073			ret = vfs_set_filelen(new_fsp, size);
4074			close_file(new_fsp,True);
4075		} else {
4076			ret = vfs_set_filelen(fsp, size);
4077		}
4078
4079		if (ret == -1)
4080			return (UNIXERROR(ERRHRD,ERRdiskfull));
4081	}
4082
4083	/*
4084	 * Finally the times.
4085	 */
4086	if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
4087		if(fsp != NULL) {
4088			/*
4089			 * This was a setfileinfo on an open file.
4090			 * NT does this a lot. We also need to
4091			 * set the time here, as it can be read by
4092			 * FindFirst/FindNext and with the patch for bug #2045
4093			 * in smbd/fileio.c it ensures that this timestamp is
4094			 * kept sticky even after a write. We save the request
4095			 * away and will set it on file close and after a write. JRA.
4096			 */
4097
4098			if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
4099				DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
4100				fsp_set_pending_modtime(fsp, tvs.modtime);
4101			}
4102
4103		}
4104		DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
4105
4106		if(file_utime(conn, fname, &tvs)!=0) {
4107			return(UNIXERROR(ERRDOS,ERRnoaccess));
4108		}
4109	}
4110
4111	SSVAL(params,0,0);
4112	send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4113
4114	return(-1);
4115}
4116
4117/****************************************************************************
4118 Reply to a TRANS2_MKDIR (make directory with extended attributes).
4119****************************************************************************/
4120
4121static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4122					char **pparams, int total_params, char **ppdata, int total_data,
4123					unsigned int max_data_bytes)
4124{
4125	char *params = *pparams;
4126	pstring directory;
4127	int ret = -1;
4128	SMB_STRUCT_STAT sbuf;
4129	BOOL bad_path = False;
4130	NTSTATUS status = NT_STATUS_OK;
4131
4132	if (!CAN_WRITE(conn))
4133		return ERROR_DOS(ERRSRV,ERRaccess);
4134
4135	if (total_params < 4)
4136		return(ERROR_DOS(ERRDOS,ERRinvalidparam));
4137
4138	srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE, &status, False);
4139	if (!NT_STATUS_IS_OK(status)) {
4140		return ERROR_NT(status);
4141	}
4142
4143	DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4144
4145	unix_convert(directory,conn,0,&bad_path,&sbuf);
4146	if (bad_path) {
4147		return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
4148	}
4149	if (check_name(directory,conn))
4150		ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
4151
4152	if(ret < 0) {
4153		DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
4154		return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
4155	}
4156
4157	/* Realloc the parameter and data sizes */
4158	params = SMB_REALLOC(*pparams,2);
4159	if(params == NULL)
4160		return ERROR_DOS(ERRDOS,ERRnomem);
4161	*pparams = params;
4162
4163	SSVAL(params,0,0);
4164
4165	send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4166
4167	return(-1);
4168}
4169
4170/****************************************************************************
4171 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4172 We don't actually do this - we just send a null response.
4173****************************************************************************/
4174
4175static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4176					char **pparams, int total_params, char **ppdata, int total_data,
4177					unsigned int max_data_bytes)
4178{
4179	static uint16 fnf_handle = 257;
4180	char *params = *pparams;
4181	uint16 info_level;
4182
4183	if (total_params < 6)
4184		return(ERROR_DOS(ERRDOS,ERRinvalidparam));
4185
4186	info_level = SVAL(params,4);
4187	DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4188
4189	switch (info_level) {
4190		case 1:
4191		case 2:
4192			break;
4193		default:
4194			return ERROR_DOS(ERRDOS,ERRunknownlevel);
4195	}
4196
4197	/* Realloc the parameter and data sizes */
4198	params = SMB_REALLOC(*pparams,6);
4199	if(params == NULL)
4200		return ERROR_DOS(ERRDOS,ERRnomem);
4201	*pparams = params;
4202
4203	SSVAL(params,0,fnf_handle);
4204	SSVAL(params,2,0); /* No changes */
4205	SSVAL(params,4,0); /* No EA errors */
4206
4207	fnf_handle++;
4208
4209	if(fnf_handle == 0)
4210		fnf_handle = 257;
4211
4212	send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
4213
4214	return(-1);
4215}
4216
4217/****************************************************************************
4218 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
4219 changes). Currently this does nothing.
4220****************************************************************************/
4221
4222static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4223					char **pparams, int total_params, char **ppdata, int total_data,
4224					unsigned int max_data_bytes)
4225{
4226	char *params = *pparams;
4227
4228	DEBUG(3,("call_trans2findnotifynext\n"));
4229
4230	/* Realloc the parameter and data sizes */
4231	params = SMB_REALLOC(*pparams,4);
4232	if(params == NULL)
4233		return ERROR_DOS(ERRDOS,ERRnomem);
4234	*pparams = params;
4235
4236	SSVAL(params,0,0); /* No changes */
4237	SSVAL(params,2,0); /* No EA errors */
4238
4239	send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
4240
4241	return(-1);
4242}
4243
4244/****************************************************************************
4245 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4246****************************************************************************/
4247
4248static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4249					char **pparams, int total_params, char **ppdata, int total_data,
4250					unsigned int max_data_bytes)
4251{
4252	char *params = *pparams;
4253  	pstring pathname;
4254	int reply_size = 0;
4255	int max_referral_level;
4256
4257	DEBUG(10,("call_trans2getdfsreferral\n"));
4258
4259	if (total_params < 2)
4260		return(ERROR_DOS(ERRDOS,ERRinvalidparam));
4261
4262	max_referral_level = SVAL(params,0);
4263
4264	if(!lp_host_msdfs())
4265		return ERROR_DOS(ERRDOS,ERRbadfunc);
4266
4267	srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
4268	if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
4269		return UNIXERROR(ERRDOS,ERRbadfile);
4270
4271	SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
4272	send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
4273
4274	return(-1);
4275}
4276
4277#define LMCAT_SPL       0x53
4278#define LMFUNC_GETJOBID 0x60
4279
4280/****************************************************************************
4281 Reply to a TRANS2_IOCTL - used for OS/2 printing.
4282****************************************************************************/
4283
4284static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4285					char **pparams, int total_params, char **ppdata, int total_data,
4286					unsigned int max_data_bytes)
4287{
4288	char *pdata = *ppdata;
4289	files_struct *fsp = file_fsp(inbuf,smb_vwv15);
4290
4291	/* check for an invalid fid before proceeding */
4292
4293	if (!fsp)
4294		return(ERROR_DOS(ERRDOS,ERRbadfid));
4295
4296	if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4297			(SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4298		pdata = SMB_REALLOC(*ppdata, 32);
4299		if(pdata == NULL)
4300			return ERROR_DOS(ERRDOS,ERRnomem);
4301		*ppdata = pdata;
4302
4303		/* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
4304			CAN ACCEPT THIS IN UNICODE. JRA. */
4305
4306		SSVAL(pdata,0,fsp->rap_print_jobid);                     /* Job number */
4307		srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
4308		srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
4309		send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
4310		return(-1);
4311	} else {
4312		DEBUG(2,("Unknown TRANS2_IOCTL\n"));
4313		return ERROR_DOS(ERRSRV,ERRerror);
4314	}
4315}
4316
4317/****************************************************************************
4318 Reply to a SMBfindclose (stop trans2 directory search).
4319****************************************************************************/
4320
4321int reply_findclose(connection_struct *conn,
4322		    char *inbuf,char *outbuf,int length,int bufsize)
4323{
4324	int outsize = 0;
4325	int dptr_num=SVALS(inbuf,smb_vwv0);
4326	START_PROFILE(SMBfindclose);
4327
4328	DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
4329
4330	dptr_close(&dptr_num);
4331
4332	outsize = set_message(outbuf,0,0,True);
4333
4334	DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
4335
4336	END_PROFILE(SMBfindclose);
4337	return(outsize);
4338}
4339
4340/****************************************************************************
4341 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
4342****************************************************************************/
4343
4344int reply_findnclose(connection_struct *conn,
4345		     char *inbuf,char *outbuf,int length,int bufsize)
4346{
4347	int outsize = 0;
4348	int dptr_num= -1;
4349	START_PROFILE(SMBfindnclose);
4350
4351	dptr_num = SVAL(inbuf,smb_vwv0);
4352
4353	DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
4354
4355	/* We never give out valid handles for a
4356	   findnotifyfirst - so any dptr_num is ok here.
4357	   Just ignore it. */
4358
4359	outsize = set_message(outbuf,0,0,True);
4360
4361	DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
4362
4363	END_PROFILE(SMBfindnclose);
4364	return(outsize);
4365}
4366
4367/****************************************************************************
4368 Reply to a SMBtranss2 - just ignore it!
4369****************************************************************************/
4370
4371int reply_transs2(connection_struct *conn,
4372		  char *inbuf,char *outbuf,int length,int bufsize)
4373{
4374	START_PROFILE(SMBtranss2);
4375	DEBUG(4,("Ignoring transs2 of length %d\n",length));
4376	END_PROFILE(SMBtranss2);
4377	return(-1);
4378}
4379
4380/****************************************************************************
4381 Reply to a SMBtrans2.
4382****************************************************************************/
4383
4384int reply_trans2(connection_struct *conn,
4385		 char *inbuf,char *outbuf,int length,int bufsize)
4386{
4387	int outsize = 0;
4388	unsigned int total_params = SVAL(inbuf, smb_tpscnt);
4389	unsigned int total_data =SVAL(inbuf, smb_tdscnt);
4390	unsigned int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
4391#if 0
4392	unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
4393	unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
4394	BOOL close_tid = BITSETW(inbuf+smb_flags,0);
4395	BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
4396	int32 timeout = IVALS(inbuf,smb_timeout);
4397#endif
4398	unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
4399	unsigned int tran_call = SVAL(inbuf, smb_setup0);
4400	char *params = NULL, *data = NULL;
4401	unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
4402	START_PROFILE(SMBtrans2);
4403
4404	if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
4405		/* Queue this open message as we are the process of an
4406		 * oplock break.  */
4407
4408		DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
4409		DEBUGADD(2,( "in oplock break state.\n"));
4410
4411		push_oplock_pending_smb_message(inbuf, length);
4412		END_PROFILE(SMBtrans2);
4413		return -1;
4414	}
4415
4416	if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
4417            && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
4418		END_PROFILE(SMBtrans2);
4419		return ERROR_DOS(ERRSRV,ERRaccess);
4420	}
4421
4422	outsize = set_message(outbuf,0,0,True);
4423
4424	/* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4425	   is so as a sanity check */
4426	if (suwcnt != 1) {
4427		/*
4428		 * Need to have rc=0 for ioctl to get job id for OS/2.
4429		 *  Network printing will fail if function is not successful.
4430		 *  Similar function in reply.c will be used if protocol
4431		 *  is LANMAN1.0 instead of LM1.2X002.
4432		 *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
4433		 *  outbuf doesn't have to be set(only job id is used).
4434		 */
4435		if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
4436				(SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4437				(SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4438			DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4439		} else {
4440			DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
4441			DEBUG(2,("Transaction is %d\n",tran_call));
4442			END_PROFILE(SMBtrans2);
4443			ERROR_DOS(ERRDOS,ERRinvalidparam);
4444		}
4445	}
4446
4447	/* Allocate the space for the maximum needed parameters and data */
4448	if (total_params > 0)
4449		params = (char *)SMB_MALLOC(total_params);
4450	if (total_data > 0)
4451		data = (char *)SMB_MALLOC(total_data);
4452
4453	if ((total_params && !params)  || (total_data && !data)) {
4454		DEBUG(2,("Out of memory in reply_trans2\n"));
4455		SAFE_FREE(params);
4456		SAFE_FREE(data);
4457		END_PROFILE(SMBtrans2);
4458		return ERROR_DOS(ERRDOS,ERRnomem);
4459	}
4460
4461	/* Copy the param and data bytes sent with this request into
4462	   the params buffer */
4463	num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
4464	num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
4465
4466	if (num_params > total_params || num_data > total_data)
4467		exit_server("invalid params in reply_trans2");
4468
4469	if(params) {
4470		unsigned int psoff = SVAL(inbuf, smb_psoff);
4471		if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
4472			goto bad_param;
4473		if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
4474				(smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
4475			goto bad_param;
4476		memcpy( params, smb_base(inbuf) + psoff, num_params);
4477	}
4478	if(data) {
4479		unsigned int dsoff = SVAL(inbuf, smb_dsoff);
4480		if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
4481			goto bad_param;
4482		if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
4483				(smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
4484			goto bad_param;
4485		memcpy( data, smb_base(inbuf) + dsoff, num_data);
4486	}
4487
4488	srv_signing_trans_start(SVAL(inbuf,smb_mid));
4489
4490	if(num_data_sofar < total_data || num_params_sofar < total_params)  {
4491		/* We need to send an interim response then receive the rest
4492		   of the parameter/data bytes */
4493		outsize = set_message(outbuf,0,0,True);
4494		srv_signing_trans_stop();
4495		if (!send_smb(smbd_server_fd(),outbuf))
4496			exit_server("reply_trans2: send_smb failed.");
4497
4498		while (num_data_sofar < total_data ||
4499		       num_params_sofar < total_params) {
4500			BOOL ret;
4501			unsigned int param_disp;
4502			unsigned int param_off;
4503			unsigned int data_disp;
4504			unsigned int data_off;
4505
4506			ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
4507
4508			/*
4509			 * The sequence number for the trans reply is always
4510			 * based on the last secondary received.
4511			 */
4512
4513			srv_signing_trans_start(SVAL(inbuf,smb_mid));
4514
4515			if ((ret &&
4516			     (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4517				outsize = set_message(outbuf,0,0,True);
4518				if(ret)
4519					DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4520				else
4521					DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4522						 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4523				goto bad_param;
4524			}
4525
4526			/* Revise total_params and total_data in case
4527                           they have changed downwards */
4528			if (SVAL(inbuf, smb_tpscnt) < total_params)
4529				total_params = SVAL(inbuf, smb_tpscnt);
4530			if (SVAL(inbuf, smb_tdscnt) < total_data)
4531				total_data = SVAL(inbuf, smb_tdscnt);
4532
4533			num_params = SVAL(inbuf,smb_spscnt);
4534			param_off = SVAL(inbuf, smb_spsoff);
4535			param_disp = SVAL(inbuf, smb_spsdisp);
4536			num_params_sofar += num_params;
4537
4538			num_data = SVAL(inbuf, smb_sdscnt);
4539			data_off = SVAL(inbuf, smb_sdsoff);
4540			data_disp = SVAL(inbuf, smb_sdsdisp);
4541			num_data_sofar += num_data;
4542
4543			if (num_params_sofar > total_params || num_data_sofar > total_data)
4544				goto bad_param;
4545
4546			if (num_params) {
4547				if (param_disp + num_params > total_params)
4548					goto bad_param;
4549				if ((param_disp + num_params < param_disp) ||
4550						(param_disp + num_params < num_params))
4551					goto bad_param;
4552				if (param_disp > total_params)
4553					goto bad_param;
4554				if ((smb_base(inbuf) + param_off + num_params >= inbuf + bufsize) ||
4555						(smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
4556					goto bad_param;
4557				if (params + param_disp < params)
4558					goto bad_param;
4559
4560				memcpy( &params[param_disp], smb_base(inbuf) + param_off, num_params);
4561			}
4562			if (num_data) {
4563				if (data_disp + num_data > total_data)
4564					goto bad_param;
4565				if ((data_disp + num_data < data_disp) ||
4566						(data_disp + num_data < num_data))
4567					goto bad_param;
4568				if (data_disp > total_data)
4569					goto bad_param;
4570				if ((smb_base(inbuf) + data_off + num_data >= inbuf + bufsize) ||
4571						(smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
4572					goto bad_param;
4573				if (data + data_disp < data)
4574					goto bad_param;
4575
4576				memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
4577			}
4578		}
4579	}
4580
4581	if (Protocol >= PROTOCOL_NT1) {
4582		SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
4583	}
4584
4585	/* Now we must call the relevant TRANS2 function */
4586	switch(tran_call)  {
4587	case TRANSACT2_OPEN:
4588		START_PROFILE_NESTED(Trans2_open);
4589		outsize = call_trans2open(conn, inbuf, outbuf, bufsize,
4590					  &params, total_params, &data, total_data, max_data_bytes);
4591		END_PROFILE_NESTED(Trans2_open);
4592		break;
4593
4594	case TRANSACT2_FINDFIRST:
4595		START_PROFILE_NESTED(Trans2_findfirst);
4596		outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
4597					  &params, total_params, &data, total_data, max_data_bytes);
4598		END_PROFILE_NESTED(Trans2_findfirst);
4599		break;
4600
4601	case TRANSACT2_FINDNEXT:
4602		START_PROFILE_NESTED(Trans2_findnext);
4603		outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize,
4604					  &params, total_params, &data, total_data, max_data_bytes);
4605		END_PROFILE_NESTED(Trans2_findnext);
4606		break;
4607
4608	case TRANSACT2_QFSINFO:
4609		START_PROFILE_NESTED(Trans2_qfsinfo);
4610		outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
4611					  &params, total_params, &data, total_data, max_data_bytes);
4612		END_PROFILE_NESTED(Trans2_qfsinfo);
4613	    break;
4614
4615#ifdef HAVE_SYS_QUOTAS
4616	case TRANSACT2_SETFSINFO:
4617		START_PROFILE_NESTED(Trans2_setfsinfo);
4618		outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize,
4619					  &params, total_params, &data, total_data, max_data_bytes);
4620		END_PROFILE_NESTED(Trans2_setfsinfo);
4621		break;
4622#endif
4623	case TRANSACT2_QPATHINFO:
4624	case TRANSACT2_QFILEINFO:
4625		START_PROFILE_NESTED(Trans2_qpathinfo);
4626		outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4627					  &params, total_params, &data, total_data, max_data_bytes);
4628		END_PROFILE_NESTED(Trans2_qpathinfo);
4629		break;
4630	case TRANSACT2_SETPATHINFO:
4631	case TRANSACT2_SETFILEINFO:
4632		START_PROFILE_NESTED(Trans2_setpathinfo);
4633		outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize,
4634					  &params, total_params, &data, total_data, max_data_bytes);
4635		END_PROFILE_NESTED(Trans2_setpathinfo);
4636		break;
4637
4638	case TRANSACT2_FINDNOTIFYFIRST:
4639		START_PROFILE_NESTED(Trans2_findnotifyfirst);
4640		outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize,
4641					  &params, total_params, &data, total_data, max_data_bytes);
4642		END_PROFILE_NESTED(Trans2_findnotifyfirst);
4643		break;
4644
4645	case TRANSACT2_FINDNOTIFYNEXT:
4646		START_PROFILE_NESTED(Trans2_findnotifynext);
4647		outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize,
4648					  &params, total_params, &data, total_data, max_data_bytes);
4649		END_PROFILE_NESTED(Trans2_findnotifynext);
4650		break;
4651	case TRANSACT2_MKDIR:
4652		START_PROFILE_NESTED(Trans2_mkdir);
4653		outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
4654					  &params, total_params, &data, total_data, max_data_bytes);
4655		END_PROFILE_NESTED(Trans2_mkdir);
4656		break;
4657
4658	case TRANSACT2_GET_DFS_REFERRAL:
4659		START_PROFILE_NESTED(Trans2_get_dfs_referral);
4660		outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
4661					  &params, total_params, &data, total_data, max_data_bytes);
4662		END_PROFILE_NESTED(Trans2_get_dfs_referral);
4663		break;
4664	case TRANSACT2_IOCTL:
4665		START_PROFILE_NESTED(Trans2_ioctl);
4666		outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
4667					  &params, total_params, &data, total_data, max_data_bytes);
4668		END_PROFILE_NESTED(Trans2_ioctl);
4669		break;
4670	default:
4671		/* Error in request */
4672		DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
4673		SAFE_FREE(params);
4674		SAFE_FREE(data);
4675		END_PROFILE(SMBtrans2);
4676		srv_signing_trans_stop();
4677		return ERROR_DOS(ERRSRV,ERRerror);
4678	}
4679
4680	/* As we do not know how many data packets will need to be
4681	   returned here the various call_trans2xxxx calls
4682	   must send their own. Thus a call_trans2xxx routine only
4683	   returns a value other than -1 when it wants to send
4684	   an error packet.
4685	*/
4686
4687	srv_signing_trans_stop();
4688
4689	SAFE_FREE(params);
4690	SAFE_FREE(data);
4691	END_PROFILE(SMBtrans2);
4692	return outsize; /* If a correct response was needed the
4693			   call_trans2xxx calls have already sent
4694			   it. If outsize != -1 then it is returning */
4695
4696  bad_param:
4697
4698	srv_signing_trans_stop();
4699	SAFE_FREE(params);
4700	SAFE_FREE(data);
4701	END_PROFILE(SMBtrans2);
4702	return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4703}
4704