1/*
2   Unix SMB/CIFS implementation.
3   Directory handling routines
4   Copyright (C) Andrew Tridgell 1992-1998
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2 of the License, or
9   (at your option) any later version.
10
11   This program is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with this program; if not, write to the Free Software
18   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19*/
20
21#include "includes.h"
22
23/*
24   This module implements directory related functions for Samba.
25*/
26
27extern struct current_user current_user;
28
29/* "Special" directory offsets. */
30#define END_OF_DIRECTORY_OFFSET ((long)-1)
31#define START_OF_DIRECTORY_OFFSET ((long)0)
32#define DOT_DOT_DIRECTORY_OFFSET ((long)0x80000000)
33
34/* Make directory handle internals available. */
35
36#define NAME_CACHE_SIZE 100
37
38struct name_cache_entry {
39	char *name;
40	long offset;
41};
42
43struct smb_Dir {
44	connection_struct *conn;
45	SMB_STRUCT_DIR *dir;
46	long offset;
47	char *dir_path;
48	struct name_cache_entry *name_cache;
49	unsigned int name_cache_index;
50	unsigned int file_number;
51};
52
53struct dptr_struct {
54	struct dptr_struct *next, *prev;
55	int dnum;
56	uint16 spid;
57	struct connection_struct *conn;
58	struct smb_Dir *dir_hnd;
59	BOOL expect_close;
60	char *wcard;
61	uint32 attr;
62	char *path;
63	BOOL has_wild; /* Set to true if the wcard entry has MS wildcard characters in it. */
64	BOOL did_stat; /* Optimisation for non-wcard searches. */
65};
66
67static struct bitmap *dptr_bmap;
68static struct dptr_struct *dirptrs;
69static int dirhandles_open = 0;
70
71#define INVALID_DPTR_KEY (-3)
72
73/****************************************************************************
74 Make a dir struct.
75****************************************************************************/
76
77void make_dir_struct(char *buf, const char *mask, const char *fname,SMB_OFF_T size,uint32 mode,time_t date, BOOL uc)
78{
79	char *p;
80	pstring mask2;
81
82	pstrcpy(mask2,mask);
83
84	if ((mode & aDIR) != 0)
85		size = 0;
86
87	memset(buf+1,' ',11);
88	if ((p = strchr_m(mask2,'.')) != NULL) {
89		*p = 0;
90		push_ascii(buf+1,mask2,8, 0);
91		push_ascii(buf+9,p+1,3, 0);
92		*p = '.';
93	} else
94		push_ascii(buf+1,mask2,11, 0);
95
96	memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
97	SCVAL(buf,21,mode);
98	srv_put_dos_date(buf,22,date);
99	SSVAL(buf,26,size & 0xFFFF);
100	SSVAL(buf,28,(size >> 16)&0xFFFF);
101	/* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
102	   Strange, but verified on W2K3. Needed for OS/2. JRA. */
103	push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
104	DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
105}
106
107/****************************************************************************
108 Initialise the dir bitmap.
109****************************************************************************/
110
111void init_dptrs(void)
112{
113	static BOOL dptrs_init=False;
114
115	if (dptrs_init)
116		return;
117
118	dptr_bmap = bitmap_allocate(MAX_DIRECTORY_HANDLES);
119
120	if (!dptr_bmap)
121		exit_server("out of memory in init_dptrs");
122
123	dptrs_init = True;
124}
125
126/****************************************************************************
127 Idle a dptr - the directory is closed but the control info is kept.
128****************************************************************************/
129
130static void dptr_idle(struct dptr_struct *dptr)
131{
132	if (dptr->dir_hnd) {
133		DEBUG(4,("Idling dptr dnum %d\n",dptr->dnum));
134		CloseDir(dptr->dir_hnd);
135		dptr->dir_hnd = NULL;
136	}
137}
138
139/****************************************************************************
140 Idle the oldest dptr.
141****************************************************************************/
142
143static void dptr_idleoldest(void)
144{
145	struct dptr_struct *dptr;
146
147	/*
148	 * Go to the end of the list.
149	 */
150	for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next)
151		;
152
153	if(!dptr) {
154		DEBUG(0,("No dptrs available to idle ?\n"));
155		return;
156	}
157
158	/*
159	 * Idle the oldest pointer.
160	 */
161
162	for(; dptr; dptr = dptr->prev) {
163		if (dptr->dir_hnd) {
164			dptr_idle(dptr);
165			return;
166		}
167	}
168}
169
170/****************************************************************************
171 Get the struct dptr_struct for a dir index.
172****************************************************************************/
173
174static struct dptr_struct *dptr_get(int key, BOOL forclose)
175{
176	struct dptr_struct *dptr;
177
178	for(dptr = dirptrs; dptr; dptr = dptr->next) {
179		if(dptr->dnum == key) {
180			if (!forclose && !dptr->dir_hnd) {
181				if (dirhandles_open >= MAX_OPEN_DIRECTORIES)
182					dptr_idleoldest();
183				DEBUG(4,("dptr_get: Reopening dptr key %d\n",key));
184				if (!(dptr->dir_hnd = OpenDir(dptr->conn, dptr->path, dptr->wcard, dptr->attr))) {
185					DEBUG(4,("dptr_get: Failed to open %s (%s)\n",dptr->path,
186						strerror(errno)));
187					return False;
188				}
189			}
190			DLIST_PROMOTE(dirptrs,dptr);
191			return dptr;
192		}
193	}
194	return(NULL);
195}
196
197/****************************************************************************
198 Get the dir path for a dir index.
199****************************************************************************/
200
201char *dptr_path(int key)
202{
203	struct dptr_struct *dptr = dptr_get(key, False);
204	if (dptr)
205		return(dptr->path);
206	return(NULL);
207}
208
209/****************************************************************************
210 Get the dir wcard for a dir index.
211****************************************************************************/
212
213char *dptr_wcard(int key)
214{
215	struct dptr_struct *dptr = dptr_get(key, False);
216	if (dptr)
217		return(dptr->wcard);
218	return(NULL);
219}
220
221/****************************************************************************
222 Get the dir attrib for a dir index.
223****************************************************************************/
224
225uint16 dptr_attr(int key)
226{
227	struct dptr_struct *dptr = dptr_get(key, False);
228	if (dptr)
229		return(dptr->attr);
230	return(0);
231}
232
233/****************************************************************************
234 Close a dptr (internal func).
235****************************************************************************/
236
237static void dptr_close_internal(struct dptr_struct *dptr)
238{
239	DEBUG(4,("closing dptr key %d\n",dptr->dnum));
240
241	DLIST_REMOVE(dirptrs, dptr);
242
243	/*
244	 * Free the dnum in the bitmap. Remember the dnum value is always
245	 * biased by one with respect to the bitmap.
246	 */
247
248	if(bitmap_query( dptr_bmap, dptr->dnum - 1) != True) {
249		DEBUG(0,("dptr_close_internal : Error - closing dnum = %d and bitmap not set !\n",
250			dptr->dnum ));
251	}
252
253	bitmap_clear(dptr_bmap, dptr->dnum - 1);
254
255	if (dptr->dir_hnd) {
256		CloseDir(dptr->dir_hnd);
257	}
258
259	/* Lanman 2 specific code */
260	SAFE_FREE(dptr->wcard);
261	string_set(&dptr->path,"");
262	SAFE_FREE(dptr);
263}
264
265/****************************************************************************
266 Close a dptr given a key.
267****************************************************************************/
268
269void dptr_close(int *key)
270{
271	struct dptr_struct *dptr;
272
273	if(*key == INVALID_DPTR_KEY)
274		return;
275
276	/* OS/2 seems to use -1 to indicate "close all directories" */
277	if (*key == -1) {
278		struct dptr_struct *next;
279		for(dptr = dirptrs; dptr; dptr = next) {
280			next = dptr->next;
281			dptr_close_internal(dptr);
282		}
283		*key = INVALID_DPTR_KEY;
284		return;
285	}
286
287	dptr = dptr_get(*key, True);
288
289	if (!dptr) {
290		DEBUG(0,("Invalid key %d given to dptr_close\n", *key));
291		return;
292	}
293
294	dptr_close_internal(dptr);
295
296	*key = INVALID_DPTR_KEY;
297}
298
299/****************************************************************************
300 Close all dptrs for a cnum.
301****************************************************************************/
302
303void dptr_closecnum(connection_struct *conn)
304{
305	struct dptr_struct *dptr, *next;
306	for(dptr = dirptrs; dptr; dptr = next) {
307		next = dptr->next;
308		if (dptr->conn == conn)
309			dptr_close_internal(dptr);
310	}
311}
312
313/****************************************************************************
314 Idle all dptrs for a cnum.
315****************************************************************************/
316
317void dptr_idlecnum(connection_struct *conn)
318{
319	struct dptr_struct *dptr;
320	for(dptr = dirptrs; dptr; dptr = dptr->next) {
321		if (dptr->conn == conn && dptr->dir_hnd)
322			dptr_idle(dptr);
323	}
324}
325
326/****************************************************************************
327 Close a dptr that matches a given path, only if it matches the spid also.
328****************************************************************************/
329
330void dptr_closepath(char *path,uint16 spid)
331{
332	struct dptr_struct *dptr, *next;
333	for(dptr = dirptrs; dptr; dptr = next) {
334		next = dptr->next;
335		if (spid == dptr->spid && strequal(dptr->path,path))
336			dptr_close_internal(dptr);
337	}
338}
339
340/****************************************************************************
341 Try and close the oldest handle not marked for
342 expect close in the hope that the client has
343 finished with that one.
344****************************************************************************/
345
346static void dptr_close_oldest(BOOL old)
347{
348	struct dptr_struct *dptr;
349
350	/*
351	 * Go to the end of the list.
352	 */
353	for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next)
354		;
355
356	if(!dptr) {
357		DEBUG(0,("No old dptrs available to close oldest ?\n"));
358		return;
359	}
360
361	/*
362	 * If 'old' is true, close the oldest oldhandle dnum (ie. 1 < dnum < 256) that
363	 * does not have expect_close set. If 'old' is false, close
364	 * one of the new dnum handles.
365	 */
366
367	for(; dptr; dptr = dptr->prev) {
368		if ((old && (dptr->dnum < 256) && !dptr->expect_close) ||
369			(!old && (dptr->dnum > 255))) {
370				dptr_close_internal(dptr);
371				return;
372		}
373	}
374}
375
376/****************************************************************************
377 Create a new dir ptr. If the flag old_handle is true then we must allocate
378 from the bitmap range 0 - 255 as old SMBsearch directory handles are only
379 one byte long. If old_handle is false we allocate from the range
380 256 - MAX_DIRECTORY_HANDLES. We bias the number we return by 1 to ensure
381 a directory handle is never zero.
382 wcard must not be zero.
383****************************************************************************/
384
385NTSTATUS dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid,
386		const char *wcard, BOOL wcard_has_wild, uint32 attr, struct dptr_struct **dptr_ret)
387{
388	struct dptr_struct *dptr = NULL;
389	struct smb_Dir *dir_hnd;
390        const char *dir2;
391	NTSTATUS status;
392
393	DEBUG(5,("dptr_create dir=%s\n", path));
394
395	if (!wcard) {
396		return NT_STATUS_INVALID_PARAMETER;
397	}
398
399	status = check_name(conn,path);
400	if (!NT_STATUS_IS_OK(status)) {
401		return status;
402	}
403
404	/* use a const pointer from here on */
405	dir2 = path;
406	if (!*dir2)
407		dir2 = ".";
408
409	dir_hnd = OpenDir(conn, dir2, wcard, attr);
410	if (!dir_hnd) {
411		return map_nt_error_from_unix(errno);
412	}
413
414	string_set(&conn->dirpath,dir2);
415
416	if (dirhandles_open >= MAX_OPEN_DIRECTORIES) {
417		dptr_idleoldest();
418	}
419
420	dptr = SMB_MALLOC_P(struct dptr_struct);
421	if(!dptr) {
422		DEBUG(0,("malloc fail in dptr_create.\n"));
423		CloseDir(dir_hnd);
424		return NT_STATUS_NO_MEMORY;
425	}
426
427	ZERO_STRUCTP(dptr);
428
429	if(old_handle) {
430
431		/*
432		 * This is an old-style SMBsearch request. Ensure the
433		 * value we return will fit in the range 1-255.
434		 */
435
436		dptr->dnum = bitmap_find(dptr_bmap, 0);
437
438		if(dptr->dnum == -1 || dptr->dnum > 254) {
439
440			/*
441			 * Try and close the oldest handle not marked for
442			 * expect close in the hope that the client has
443			 * finished with that one.
444			 */
445
446			dptr_close_oldest(True);
447
448			/* Now try again... */
449			dptr->dnum = bitmap_find(dptr_bmap, 0);
450			if(dptr->dnum == -1 || dptr->dnum > 254) {
451				DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr->dnum));
452				SAFE_FREE(dptr);
453				CloseDir(dir_hnd);
454				return NT_STATUS_TOO_MANY_OPENED_FILES;
455			}
456		}
457	} else {
458
459		/*
460		 * This is a new-style trans2 request. Allocate from
461		 * a range that will return 256 - MAX_DIRECTORY_HANDLES.
462		 */
463
464		dptr->dnum = bitmap_find(dptr_bmap, 255);
465
466		if(dptr->dnum == -1 || dptr->dnum < 255) {
467
468			/*
469			 * Try and close the oldest handle close in the hope that
470			 * the client has finished with that one. This will only
471			 * happen in the case of the Win98 client bug where it leaks
472			 * directory handles.
473			 */
474
475			dptr_close_oldest(False);
476
477			/* Now try again... */
478			dptr->dnum = bitmap_find(dptr_bmap, 255);
479
480			if(dptr->dnum == -1 || dptr->dnum < 255) {
481				DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr->dnum));
482				SAFE_FREE(dptr);
483				CloseDir(dir_hnd);
484				return NT_STATUS_TOO_MANY_OPENED_FILES;
485			}
486		}
487	}
488
489	bitmap_set(dptr_bmap, dptr->dnum);
490
491	dptr->dnum += 1; /* Always bias the dnum by one - no zero dnums allowed. */
492
493	string_set(&dptr->path,dir2);
494	dptr->conn = conn;
495	dptr->dir_hnd = dir_hnd;
496	dptr->spid = spid;
497	dptr->expect_close = expect_close;
498	dptr->wcard = SMB_STRDUP(wcard);
499	if (!dptr->wcard) {
500		bitmap_clear(dptr_bmap, dptr->dnum - 1);
501		SAFE_FREE(dptr);
502		CloseDir(dir_hnd);
503		return NT_STATUS_NO_MEMORY;
504	}
505	if (lp_posix_pathnames() || (wcard[0] == '.' && wcard[1] == 0)) {
506		dptr->has_wild = True;
507	} else {
508		dptr->has_wild = wcard_has_wild;
509	}
510
511	dptr->attr = attr;
512
513	DLIST_ADD(dirptrs, dptr);
514
515	DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n",
516		dptr->dnum,path,expect_close));
517
518	*dptr_ret = dptr;
519
520	return NT_STATUS_OK;
521}
522
523
524/****************************************************************************
525 Wrapper functions to access the lower level directory handles.
526****************************************************************************/
527
528int dptr_CloseDir(struct dptr_struct *dptr)
529{
530	DLIST_REMOVE(dirptrs, dptr);
531	return CloseDir(dptr->dir_hnd);
532}
533
534void dptr_SeekDir(struct dptr_struct *dptr, long offset)
535{
536	SeekDir(dptr->dir_hnd, offset);
537}
538
539long dptr_TellDir(struct dptr_struct *dptr)
540{
541	return TellDir(dptr->dir_hnd);
542}
543
544BOOL dptr_has_wild(struct dptr_struct *dptr)
545{
546	return dptr->has_wild;
547}
548
549int dptr_dnum(struct dptr_struct *dptr)
550{
551	return dptr->dnum;
552}
553
554/****************************************************************************
555 Return the next visible file name, skipping veto'd and invisible files.
556****************************************************************************/
557
558static const char *dptr_normal_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT_STAT *pst)
559{
560	/* Normal search for the next file. */
561	const char *name;
562	while ((name = ReadDirName(dptr->dir_hnd, poffset)) != NULL) {
563		if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) {
564			return name;
565		}
566	}
567	return NULL;
568}
569
570/****************************************************************************
571 Return the next visible file name, skipping veto'd and invisible files.
572****************************************************************************/
573
574const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset, SMB_STRUCT_STAT *pst)
575{
576	SET_STAT_INVALID(*pst);
577
578	if (dptr->has_wild) {
579		return dptr_normal_ReadDirName(dptr, poffset, pst);
580	}
581
582	/* If poffset is -1 then we know we returned this name before and we have
583	   no wildcards. We're at the end of the directory. */
584	if (*poffset == END_OF_DIRECTORY_OFFSET) {
585		return NULL;
586	}
587
588	if (!dptr->did_stat) {
589		pstring pathreal;
590
591		/* We know the stored wcard contains no wildcard characters. See if we can match
592		   with a stat call. If we can't, then set did_stat to true to
593		   ensure we only do this once and keep searching. */
594
595		dptr->did_stat = True;
596
597		/* First check if it should be visible. */
598		if (!is_visible_file(dptr->conn, dptr->path, dptr->wcard, pst, True)) {
599			/* This only returns False if the file was found, but
600			   is explicitly not visible. Set us to end of directory,
601			   but return NULL as we know we can't ever find it. */
602			dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
603			return NULL;
604		}
605
606		if (VALID_STAT(*pst)) {
607			/* We need to set the underlying dir_hnd offset to -1 also as
608			   this function is usually called with the output from TellDir. */
609			dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
610			return dptr->wcard;
611		}
612
613		pstrcpy(pathreal,dptr->path);
614		pstrcat(pathreal,"/");
615		pstrcat(pathreal,dptr->wcard);
616
617		if (SMB_VFS_STAT(dptr->conn,pathreal,pst) == 0) {
618			/* We need to set the underlying dir_hnd offset to -1 also as
619			   this function is usually called with the output from TellDir. */
620			dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
621			return dptr->wcard;
622		} else {
623			/* If we get any other error than ENOENT or ENOTDIR
624			   then the file exists we just can't stat it. */
625			if (errno != ENOENT && errno != ENOTDIR) {
626				/* We need to set the underlying dir_hdn offset to -1 also as
627				   this function is usually called with the output from TellDir. */
628				dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
629				return dptr->wcard;
630			}
631		}
632
633		/* In case sensitive mode we don't search - we know if it doesn't exist
634		   with a stat we will fail. */
635
636		if (dptr->conn->case_sensitive) {
637			/* We need to set the underlying dir_hnd offset to -1 also as
638			   this function is usually called with the output from TellDir. */
639			dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
640			return NULL;
641		}
642	}
643	return dptr_normal_ReadDirName(dptr, poffset, pst);
644}
645
646/****************************************************************************
647 Search for a file by name, skipping veto'ed and not visible files.
648****************************************************************************/
649
650BOOL dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, SMB_STRUCT_STAT *pst)
651{
652	SET_STAT_INVALID(*pst);
653
654	if (!dptr->has_wild && (dptr->dir_hnd->offset == END_OF_DIRECTORY_OFFSET)) {
655		/* This is a singleton directory and we're already at the end. */
656		*poffset = END_OF_DIRECTORY_OFFSET;
657		return False;
658	}
659
660	return SearchDir(dptr->dir_hnd, name, poffset);
661}
662
663/****************************************************************************
664 Add the name we're returning into the underlying cache.
665****************************************************************************/
666
667void dptr_DirCacheAdd(struct dptr_struct *dptr, const char *name, long offset)
668{
669	DirCacheAdd(dptr->dir_hnd, name, offset);
670}
671
672/****************************************************************************
673 Fill the 5 byte server reserved dptr field.
674****************************************************************************/
675
676BOOL dptr_fill(char *buf1,unsigned int key)
677{
678	unsigned char *buf = (unsigned char *)buf1;
679	struct dptr_struct *dptr = dptr_get(key, False);
680	uint32 offset;
681	if (!dptr) {
682		DEBUG(1,("filling null dirptr %d\n",key));
683		return(False);
684	}
685	offset = (uint32)TellDir(dptr->dir_hnd);
686	DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key,
687		(long)dptr->dir_hnd,(int)offset));
688	buf[0] = key;
689	SIVAL(buf,1,offset);
690	return(True);
691}
692
693/****************************************************************************
694 Fetch the dir ptr and seek it given the 5 byte server field.
695****************************************************************************/
696
697struct dptr_struct *dptr_fetch(char *buf,int *num)
698{
699	unsigned int key = *(unsigned char *)buf;
700	struct dptr_struct *dptr = dptr_get(key, False);
701	uint32 offset;
702	long seekoff;
703
704	if (!dptr) {
705		DEBUG(3,("fetched null dirptr %d\n",key));
706		return(NULL);
707	}
708	*num = key;
709	offset = IVAL(buf,1);
710	if (offset == (uint32)-1) {
711		seekoff = END_OF_DIRECTORY_OFFSET;
712	} else {
713		seekoff = (long)offset;
714	}
715	SeekDir(dptr->dir_hnd,seekoff);
716	DEBUG(3,("fetching dirptr %d for path %s at offset %d\n",
717		key,dptr_path(key),(int)seekoff));
718	return(dptr);
719}
720
721/****************************************************************************
722 Fetch the dir ptr.
723****************************************************************************/
724
725struct dptr_struct *dptr_fetch_lanman2(int dptr_num)
726{
727	struct dptr_struct *dptr  = dptr_get(dptr_num, False);
728
729	if (!dptr) {
730		DEBUG(3,("fetched null dirptr %d\n",dptr_num));
731		return(NULL);
732	}
733	DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr_path(dptr_num)));
734	return(dptr);
735}
736
737/****************************************************************************
738 Check that a file matches a particular file type.
739****************************************************************************/
740
741BOOL dir_check_ftype(connection_struct *conn, uint32 mode, uint32 dirtype)
742{
743	uint32 mask;
744
745	/* Check the "may have" search bits. */
746	if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0)
747		return False;
748
749	/* Check the "must have" bits, which are the may have bits shifted eight */
750	/* If must have bit is set, the file/dir can not be returned in search unless the matching
751		file attribute is set */
752	mask = ((dirtype >> 8) & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM)); /* & 0x37 */
753	if(mask) {
754		if((mask & (mode & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM))) == mask)   /* check if matching attribute present */
755			return True;
756		else
757			return False;
758	}
759
760	return True;
761}
762
763static BOOL mangle_mask_match(connection_struct *conn, fstring filename, char *mask)
764{
765	mangle_map(filename,True,False,conn->params);
766	return mask_match_search(filename,mask,False);
767}
768
769/****************************************************************************
770 Get an 8.3 directory entry.
771****************************************************************************/
772
773BOOL get_dir_entry(connection_struct *conn,char *mask,uint32 dirtype, pstring fname,
774                   SMB_OFF_T *size,uint32 *mode,time_t *date,BOOL check_descend)
775{
776	const char *dname;
777	BOOL found = False;
778	SMB_STRUCT_STAT sbuf;
779	pstring path;
780	pstring pathreal;
781	pstring filename;
782	BOOL needslash;
783
784	*path = *pathreal = *filename = 0;
785
786	needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
787
788	if (!conn->dirptr)
789		return(False);
790
791	while (!found) {
792		long curoff = dptr_TellDir(conn->dirptr);
793		dname = dptr_ReadDirName(conn->dirptr, &curoff, &sbuf);
794
795		DEBUG(6,("readdir on dirptr 0x%lx now at offset %ld\n",
796			(long)conn->dirptr,TellDir(conn->dirptr->dir_hnd)));
797
798		if (dname == NULL)
799			return(False);
800
801		pstrcpy(filename,dname);
802
803		/* notice the special *.* handling. This appears to be the only difference
804			between the wildcard handling in this routine and in the trans2 routines.
805			see masktest for a demo
806		*/
807		if ((strcmp(mask,"*.*") == 0) ||
808		    mask_match_search(filename,mask,False) ||
809		    mangle_mask_match(conn,filename,mask)) {
810
811			if (!mangle_is_8_3(filename, False, conn->params))
812				mangle_map(filename,True,False,
813					   conn->params);
814
815			pstrcpy(fname,filename);
816			*path = 0;
817			pstrcpy(path,conn->dirpath);
818			if(needslash)
819				pstrcat(path,"/");
820			pstrcpy(pathreal,path);
821			pstrcat(path,fname);
822			pstrcat(pathreal,dname);
823			if (!VALID_STAT(sbuf) && (SMB_VFS_STAT(conn, pathreal, &sbuf)) != 0) {
824				DEBUG(5,("Couldn't stat 1 [%s]. Error = %s\n",path, strerror(errno) ));
825				continue;
826			}
827
828			*mode = dos_mode(conn,pathreal,&sbuf);
829
830			if (!dir_check_ftype(conn,*mode,dirtype)) {
831				DEBUG(5,("[%s] attribs 0x%x didn't match 0x%x\n",filename,(unsigned int)*mode,(unsigned int)dirtype));
832				continue;
833			}
834
835			*size = sbuf.st_size;
836			*date = sbuf.st_mtime;
837
838			DEBUG(3,("get_dir_entry mask=[%s] found %s fname=%s\n",mask, pathreal,fname));
839
840			found = True;
841
842			DirCacheAdd(conn->dirptr->dir_hnd, dname, curoff);
843		}
844	}
845
846	return(found);
847}
848
849/*******************************************************************
850 Check to see if a user can read a file. This is only approximate,
851 it is used as part of the "hide unreadable" option. Don't
852 use it for anything security sensitive.
853********************************************************************/
854
855static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
856{
857	SEC_DESC *psd = NULL;
858	size_t sd_size;
859	files_struct *fsp;
860	NTSTATUS status;
861	uint32 access_granted;
862
863	/*
864	 * If user is a member of the Admin group
865	 * we never hide files from them.
866	 */
867
868	if (conn->admin_user) {
869		return True;
870	}
871
872	/* If we can't stat it does not show it */
873	if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0)) {
874		DEBUG(10,("user_can_read_file: SMB_VFS_STAT failed for file %s with error %s\n",
875			name, strerror(errno) ));
876		return False;
877	}
878
879	/* Pseudo-open the file (note - no fd's created). */
880
881	if(S_ISDIR(pst->st_mode)) {
882		 status = open_directory(conn, name, pst,
883			READ_CONTROL_ACCESS,
884			FILE_SHARE_READ|FILE_SHARE_WRITE,
885			FILE_OPEN,
886			0, /* no create options. */
887			FILE_ATTRIBUTE_DIRECTORY,
888			NULL, &fsp);
889	} else {
890		status = open_file_stat(conn, name, pst, &fsp);
891	}
892
893	if (!NT_STATUS_IS_OK(status)) {
894		return False;
895	}
896
897	/* Get NT ACL -allocated in main loop talloc context. No free needed here. */
898	sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fh->fd,
899			(OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
900	close_file(fsp, NORMAL_CLOSE);
901
902	/* No access if SD get failed. */
903	if (!sd_size) {
904		return False;
905	}
906
907	return se_access_check(psd, current_user.nt_user_token, FILE_READ_DATA,
908                                 &access_granted, &status);
909}
910
911/*******************************************************************
912 Check to see if a user can write a file (and only files, we do not
913 check dirs on this one). This is only approximate,
914 it is used as part of the "hide unwriteable" option. Don't
915 use it for anything security sensitive.
916********************************************************************/
917
918static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
919{
920	SEC_DESC *psd = NULL;
921	size_t sd_size;
922	files_struct *fsp;
923	int info;
924	NTSTATUS status;
925	uint32 access_granted;
926
927	/*
928	 * If user is a member of the Admin group
929	 * we never hide files from them.
930	 */
931
932	if (conn->admin_user) {
933		return True;
934	}
935
936	/* If we can't stat it does not show it */
937	if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0)) {
938		return False;
939	}
940
941	/* Pseudo-open the file */
942
943	if(S_ISDIR(pst->st_mode)) {
944		return True;
945	} else {
946		status = open_file_ntcreate(conn, name, pst,
947			FILE_WRITE_ATTRIBUTES,
948			FILE_SHARE_READ|FILE_SHARE_WRITE,
949			FILE_OPEN,
950			0,
951			FILE_ATTRIBUTE_NORMAL,
952			INTERNAL_OPEN_ONLY,
953			&info, &fsp);
954	}
955
956	if (!NT_STATUS_IS_OK(status)) {
957		return False;
958	}
959
960	/* Get NT ACL -allocated in main loop talloc context. No free needed here. */
961	sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fh->fd,
962			(OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd);
963	close_file(fsp, NORMAL_CLOSE);
964
965	/* No access if SD get failed. */
966	if (!sd_size)
967		return False;
968
969	return se_access_check(psd, current_user.nt_user_token, FILE_WRITE_DATA,
970                                 &access_granted, &status);
971}
972
973/*******************************************************************
974  Is a file a "special" type ?
975********************************************************************/
976
977static BOOL file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
978{
979	/*
980	 * If user is a member of the Admin group
981	 * we never hide files from them.
982	 */
983
984	if (conn->admin_user)
985		return False;
986
987	/* If we can't stat it does not show it */
988	if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0))
989		return True;
990
991	if (S_ISREG(pst->st_mode) || S_ISDIR(pst->st_mode) || S_ISLNK(pst->st_mode))
992		return False;
993
994	return True;
995}
996
997/*******************************************************************
998 Should the file be seen by the client ?
999********************************************************************/
1000
1001BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char *name, SMB_STRUCT_STAT *pst, BOOL use_veto)
1002{
1003	BOOL hide_unreadable = lp_hideunreadable(SNUM(conn));
1004	BOOL hide_unwriteable = lp_hideunwriteable_files(SNUM(conn));
1005	BOOL hide_special = lp_hide_special_files(SNUM(conn));
1006
1007	SET_STAT_INVALID(*pst);
1008
1009	if ((strcmp(".",name) == 0) || (strcmp("..",name) == 0)) {
1010		return True; /* . and .. are always visible. */
1011	}
1012
1013	/* If it's a vetoed file, pretend it doesn't even exist */
1014	if (use_veto && IS_VETO_PATH(conn, name)) {
1015		DEBUG(10,("is_visible_file: file %s is vetoed.\n", name ));
1016		return False;
1017	}
1018
1019	if (hide_unreadable || hide_unwriteable || hide_special) {
1020		pstring link_target;
1021		char *entry = NULL;
1022
1023		if (asprintf(&entry, "%s/%s", dir_path, name) == -1) {
1024			return False;
1025		}
1026
1027		/* If it's a dfs symlink, ignore _hide xxxx_ options */
1028		if (lp_host_msdfs() &&
1029				lp_msdfs_root(SNUM(conn)) &&
1030				is_msdfs_link(conn, entry, link_target, NULL)) {
1031			SAFE_FREE(entry);
1032			return True;
1033		}
1034
1035		/* Honour _hide unreadable_ option */
1036		if (hide_unreadable && !user_can_read_file(conn, entry, pst)) {
1037			DEBUG(10,("is_visible_file: file %s is unreadable.\n", entry ));
1038			SAFE_FREE(entry);
1039			return False;
1040		}
1041		/* Honour _hide unwriteable_ option */
1042		if (hide_unwriteable && !user_can_write_file(conn, entry, pst)) {
1043			DEBUG(10,("is_visible_file: file %s is unwritable.\n", entry ));
1044			SAFE_FREE(entry);
1045			return False;
1046		}
1047		/* Honour _hide_special_ option */
1048		if (hide_special && file_is_special(conn, entry, pst)) {
1049			DEBUG(10,("is_visible_file: file %s is special.\n", entry ));
1050			SAFE_FREE(entry);
1051			return False;
1052		}
1053		SAFE_FREE(entry);
1054	}
1055	return True;
1056}
1057
1058/*******************************************************************
1059 Open a directory.
1060********************************************************************/
1061
1062struct smb_Dir *OpenDir(connection_struct *conn, const char *name, const char *mask, uint32 attr)
1063{
1064	struct smb_Dir *dirp = SMB_MALLOC_P(struct smb_Dir);
1065	if (!dirp) {
1066		return NULL;
1067	}
1068	ZERO_STRUCTP(dirp);
1069
1070	dirp->conn = conn;
1071
1072	dirp->dir_path = SMB_STRDUP(name);
1073	if (!dirp->dir_path) {
1074		goto fail;
1075	}
1076	dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path, mask, attr);
1077	if (!dirp->dir) {
1078		DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp->dir_path, strerror(errno) ));
1079		goto fail;
1080	}
1081
1082	dirp->name_cache = SMB_CALLOC_ARRAY(struct name_cache_entry, NAME_CACHE_SIZE);
1083	if (!dirp->name_cache) {
1084		goto fail;
1085	}
1086
1087	dirhandles_open++;
1088	return dirp;
1089
1090  fail:
1091
1092	if (dirp) {
1093		if (dirp->dir) {
1094			SMB_VFS_CLOSEDIR(conn,dirp->dir);
1095		}
1096		SAFE_FREE(dirp->dir_path);
1097		SAFE_FREE(dirp->name_cache);
1098		SAFE_FREE(dirp);
1099	}
1100	return NULL;
1101}
1102
1103
1104/*******************************************************************
1105 Close a directory.
1106********************************************************************/
1107
1108int CloseDir(struct smb_Dir *dirp)
1109{
1110	int i, ret = 0;
1111
1112	if (dirp->dir) {
1113		ret = SMB_VFS_CLOSEDIR(dirp->conn,dirp->dir);
1114	}
1115	SAFE_FREE(dirp->dir_path);
1116	if (dirp->name_cache) {
1117		for (i = 0; i < NAME_CACHE_SIZE; i++) {
1118			SAFE_FREE(dirp->name_cache[i].name);
1119		}
1120	}
1121	SAFE_FREE(dirp->name_cache);
1122	SAFE_FREE(dirp);
1123	dirhandles_open--;
1124	return ret;
1125}
1126
1127/*******************************************************************
1128 Read from a directory. Also return current offset.
1129 Don't check for veto or invisible files.
1130********************************************************************/
1131
1132const char *ReadDirName(struct smb_Dir *dirp, long *poffset)
1133{
1134	const char *n;
1135	connection_struct *conn = dirp->conn;
1136
1137	/* Cheat to allow . and .. to be the first entries returned. */
1138	if (((*poffset == START_OF_DIRECTORY_OFFSET) || (*poffset == DOT_DOT_DIRECTORY_OFFSET)) && (dirp->file_number < 2)) {
1139		if (dirp->file_number == 0) {
1140			n = ".";
1141			*poffset = dirp->offset = START_OF_DIRECTORY_OFFSET;
1142		} else {
1143			*poffset = dirp->offset = DOT_DOT_DIRECTORY_OFFSET;
1144			n = "..";
1145		}
1146		dirp->file_number++;
1147		return n;
1148	} else if (*poffset == END_OF_DIRECTORY_OFFSET) {
1149		*poffset = dirp->offset = END_OF_DIRECTORY_OFFSET;
1150		return NULL;
1151	} else {
1152		/* A real offset, seek to it. */
1153		SeekDir(dirp, *poffset);
1154	}
1155
1156	while ((n = vfs_readdirname(conn, dirp->dir))) {
1157		/* Ignore . and .. - we've already returned them. */
1158		if (*n == '.') {
1159			if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
1160				continue;
1161			}
1162		}
1163		*poffset = dirp->offset = SMB_VFS_TELLDIR(conn, dirp->dir);
1164		dirp->file_number++;
1165		return n;
1166	}
1167	*poffset = dirp->offset = END_OF_DIRECTORY_OFFSET;
1168	return NULL;
1169}
1170
1171/*******************************************************************
1172 Rewind to the start.
1173********************************************************************/
1174
1175void RewindDir(struct smb_Dir *dirp, long *poffset)
1176{
1177	SMB_VFS_REWINDDIR(dirp->conn, dirp->dir);
1178	dirp->file_number = 0;
1179	dirp->offset = START_OF_DIRECTORY_OFFSET;
1180	*poffset = START_OF_DIRECTORY_OFFSET;
1181}
1182
1183/*******************************************************************
1184 Seek a dir.
1185********************************************************************/
1186
1187void SeekDir(struct smb_Dir *dirp, long offset)
1188{
1189	if (offset != dirp->offset) {
1190		if (offset == START_OF_DIRECTORY_OFFSET) {
1191			RewindDir(dirp, &offset);
1192			/*
1193			 * Ok we should really set the file number here
1194			 * to 1 to enable ".." to be returned next. Trouble
1195			 * is I'm worried about callers using SeekDir(dirp,0)
1196			 * as equivalent to RewindDir(). So leave this alone
1197			 * for now.
1198			 */
1199		} else if  (offset == DOT_DOT_DIRECTORY_OFFSET) {
1200			RewindDir(dirp, &offset);
1201			/*
1202			 * Set the file number to 2 - we want to get the first
1203			 * real file entry (the one we return after "..")
1204			 * on the next ReadDir.
1205			 */
1206			dirp->file_number = 2;
1207		} else if (offset == END_OF_DIRECTORY_OFFSET) {
1208			; /* Don't seek in this case. */
1209		} else {
1210			SMB_VFS_SEEKDIR(dirp->conn, dirp->dir, offset);
1211		}
1212		dirp->offset = offset;
1213	}
1214}
1215
1216/*******************************************************************
1217 Tell a dir position.
1218********************************************************************/
1219
1220long TellDir(struct smb_Dir *dirp)
1221{
1222	return(dirp->offset);
1223}
1224
1225/*******************************************************************
1226 Add an entry into the dcache.
1227********************************************************************/
1228
1229void DirCacheAdd(struct smb_Dir *dirp, const char *name, long offset)
1230{
1231	struct name_cache_entry *e;
1232
1233	dirp->name_cache_index = (dirp->name_cache_index+1) % NAME_CACHE_SIZE;
1234	e = &dirp->name_cache[dirp->name_cache_index];
1235	SAFE_FREE(e->name);
1236	e->name = SMB_STRDUP(name);
1237	e->offset = offset;
1238}
1239
1240/*******************************************************************
1241 Find an entry by name. Leave us at the offset after it.
1242 Don't check for veto or invisible files.
1243********************************************************************/
1244
1245BOOL SearchDir(struct smb_Dir *dirp, const char *name, long *poffset)
1246{
1247	int i;
1248	const char *entry;
1249	connection_struct *conn = dirp->conn;
1250
1251	/* Search back in the name cache. */
1252	for (i = dirp->name_cache_index; i >= 0; i--) {
1253		struct name_cache_entry *e = &dirp->name_cache[i];
1254		if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1255			*poffset = e->offset;
1256			SeekDir(dirp, e->offset);
1257			return True;
1258		}
1259	}
1260	for (i = NAME_CACHE_SIZE-1; i > dirp->name_cache_index; i--) {
1261		struct name_cache_entry *e = &dirp->name_cache[i];
1262		if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1263			*poffset = e->offset;
1264			SeekDir(dirp, e->offset);
1265			return True;
1266		}
1267	}
1268
1269	/* Not found in the name cache. Rewind directory and start from scratch. */
1270	SMB_VFS_REWINDDIR(conn, dirp->dir);
1271	dirp->file_number = 0;
1272	*poffset = START_OF_DIRECTORY_OFFSET;
1273	while ((entry = ReadDirName(dirp, poffset))) {
1274		if (conn->case_sensitive ? (strcmp(entry, name) == 0) : strequal(entry, name)) {
1275			return True;
1276		}
1277	}
1278	return False;
1279}
1280
1281/*****************************************************************
1282 Is this directory empty ?
1283*****************************************************************/
1284
1285NTSTATUS can_delete_directory(struct connection_struct *conn,
1286				const char *dirname)
1287{
1288	NTSTATUS status = NT_STATUS_OK;
1289	long dirpos = 0;
1290	const char *dname;
1291	struct smb_Dir *dir_hnd = OpenDir(conn, dirname, NULL, 0);
1292
1293	if (!dir_hnd) {
1294		return map_nt_error_from_unix(errno);
1295	}
1296
1297	while ((dname = ReadDirName(dir_hnd,&dirpos))) {
1298		SMB_STRUCT_STAT st;
1299
1300		/* Quick check for "." and ".." */
1301		if (dname[0] == '.') {
1302			if (!dname[1] || (dname[1] == '.' && !dname[2])) {
1303				continue;
1304			}
1305		}
1306
1307		if (!is_visible_file(conn, dirname, dname, &st, True)) {
1308			continue;
1309		}
1310
1311		DEBUG(10,("can_delete_directory: got name %s - can't delete\n", dname ));
1312		status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1313		break;
1314	}
1315	CloseDir(dir_hnd);
1316
1317	return status;
1318}
1319