libcli/smbreadline/smbreadline.h: fix licence/copyright
[Samba.git] / source3 / smbd / dir.c
blob9969693e7b861e063c2e5c160d797d1bdb141d50
1 /*
2 Unix SMB/CIFS implementation.
3 Directory handling routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Jeremy Allison 2007
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "includes.h"
22 #include "system/filesys.h"
23 #include "smbd/smbd.h"
24 #include "smbd/globals.h"
25 #include "libcli/security/security.h"
28 This module implements directory related functions for Samba.
31 /* "Special" directory offsets. */
32 #define END_OF_DIRECTORY_OFFSET ((long)-1)
33 #define START_OF_DIRECTORY_OFFSET ((long)0)
34 #define DOT_DOT_DIRECTORY_OFFSET ((long)0x80000000)
36 /* Make directory handle internals available. */
38 struct name_cache_entry {
39 char *name;
40 long offset;
43 struct smb_Dir {
44 connection_struct *conn;
45 SMB_STRUCT_DIR *dir;
46 long offset;
47 char *dir_path;
48 size_t name_cache_size;
49 struct name_cache_entry *name_cache;
50 unsigned int name_cache_index;
51 unsigned int file_number;
54 struct dptr_struct {
55 struct dptr_struct *next, *prev;
56 int dnum;
57 uint16 spid;
58 struct connection_struct *conn;
59 struct smb_Dir *dir_hnd;
60 bool expect_close;
61 char *wcard;
62 uint32 attr;
63 char *path;
64 bool has_wild; /* Set to true if the wcard entry has MS wildcard characters in it. */
65 bool did_stat; /* Optimisation for non-wcard searches. */
68 static struct smb_Dir *OpenDir_fsp(TALLOC_CTX *mem_ctx, connection_struct *conn,
69 files_struct *fsp,
70 const char *mask,
71 uint32 attr);
73 #define INVALID_DPTR_KEY (-3)
75 /****************************************************************************
76 Make a dir struct.
77 ****************************************************************************/
79 bool make_dir_struct(TALLOC_CTX *ctx,
80 char *buf,
81 const char *mask,
82 const char *fname,
83 SMB_OFF_T size,
84 uint32 mode,
85 time_t date,
86 bool uc)
88 char *p;
89 char *mask2 = talloc_strdup(ctx, mask);
91 if (!mask2) {
92 return False;
95 if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
96 size = 0;
99 memset(buf+1,' ',11);
100 if ((p = strchr_m(mask2,'.')) != NULL) {
101 *p = 0;
102 push_ascii(buf+1,mask2,8, 0);
103 push_ascii(buf+9,p+1,3, 0);
104 *p = '.';
105 } else {
106 push_ascii(buf+1,mask2,11, 0);
109 memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
110 SCVAL(buf,21,mode);
111 srv_put_dos_date(buf,22,date);
112 SSVAL(buf,26,size & 0xFFFF);
113 SSVAL(buf,28,(size >> 16)&0xFFFF);
114 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
115 Strange, but verified on W2K3. Needed for OS/2. JRA. */
116 push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
117 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
118 return True;
121 /****************************************************************************
122 Initialise the dir bitmap.
123 ****************************************************************************/
125 bool init_dptrs(struct smbd_server_connection *sconn)
127 if (sconn->searches.dptr_bmap) {
128 return true;
131 sconn->searches.dptr_bmap = bitmap_talloc(
132 sconn, MAX_DIRECTORY_HANDLES);
134 if (sconn->searches.dptr_bmap == NULL) {
135 return false;
138 return true;
141 /****************************************************************************
142 Idle a dptr - the directory is closed but the control info is kept.
143 ****************************************************************************/
145 static void dptr_idle(struct dptr_struct *dptr)
147 if (dptr->dir_hnd) {
148 DEBUG(4,("Idling dptr dnum %d\n",dptr->dnum));
149 TALLOC_FREE(dptr->dir_hnd);
153 /****************************************************************************
154 Idle the oldest dptr.
155 ****************************************************************************/
157 static void dptr_idleoldest(struct smbd_server_connection *sconn)
159 struct dptr_struct *dptr;
162 * Go to the end of the list.
164 dptr = DLIST_TAIL(sconn->searches.dirptrs);
166 if(!dptr) {
167 DEBUG(0,("No dptrs available to idle ?\n"));
168 return;
172 * Idle the oldest pointer.
175 for(; dptr; dptr = DLIST_PREV(dptr)) {
176 if (dptr->dir_hnd) {
177 dptr_idle(dptr);
178 return;
183 /****************************************************************************
184 Get the struct dptr_struct for a dir index.
185 ****************************************************************************/
187 static struct dptr_struct *dptr_get(struct smbd_server_connection *sconn,
188 int key, bool forclose)
190 struct dptr_struct *dptr;
192 for(dptr = sconn->searches.dirptrs; dptr; dptr = dptr->next) {
193 if(dptr->dnum == key) {
194 if (!forclose && !dptr->dir_hnd) {
195 if (sconn->searches.dirhandles_open >= MAX_OPEN_DIRECTORIES)
196 dptr_idleoldest(sconn);
197 DEBUG(4,("dptr_get: Reopening dptr key %d\n",key));
198 if (!(dptr->dir_hnd = OpenDir(
199 NULL, dptr->conn, dptr->path,
200 dptr->wcard, dptr->attr))) {
201 DEBUG(4,("dptr_get: Failed to open %s (%s)\n",dptr->path,
202 strerror(errno)));
203 return False;
206 DLIST_PROMOTE(sconn->searches.dirptrs,dptr);
207 return dptr;
210 return(NULL);
213 /****************************************************************************
214 Get the dir path for a dir index.
215 ****************************************************************************/
217 char *dptr_path(struct smbd_server_connection *sconn, int key)
219 struct dptr_struct *dptr = dptr_get(sconn, key, false);
220 if (dptr)
221 return(dptr->path);
222 return(NULL);
225 /****************************************************************************
226 Get the dir wcard for a dir index.
227 ****************************************************************************/
229 char *dptr_wcard(struct smbd_server_connection *sconn, int key)
231 struct dptr_struct *dptr = dptr_get(sconn, key, false);
232 if (dptr)
233 return(dptr->wcard);
234 return(NULL);
237 /****************************************************************************
238 Get the dir attrib for a dir index.
239 ****************************************************************************/
241 uint16 dptr_attr(struct smbd_server_connection *sconn, int key)
243 struct dptr_struct *dptr = dptr_get(sconn, key, false);
244 if (dptr)
245 return(dptr->attr);
246 return(0);
249 /****************************************************************************
250 Close a dptr (internal func).
251 ****************************************************************************/
253 static void dptr_close_internal(struct dptr_struct *dptr)
255 struct smbd_server_connection *sconn = dptr->conn->sconn;
257 DEBUG(4,("closing dptr key %d\n",dptr->dnum));
259 if (sconn == NULL) {
260 goto done;
263 DLIST_REMOVE(sconn->searches.dirptrs, dptr);
266 * Free the dnum in the bitmap. Remember the dnum value is always
267 * biased by one with respect to the bitmap.
270 if (!bitmap_query(sconn->searches.dptr_bmap, dptr->dnum - 1)) {
271 DEBUG(0,("dptr_close_internal : Error - closing dnum = %d and bitmap not set !\n",
272 dptr->dnum ));
275 bitmap_clear(sconn->searches.dptr_bmap, dptr->dnum - 1);
277 done:
278 TALLOC_FREE(dptr->dir_hnd);
280 /* Lanman 2 specific code */
281 SAFE_FREE(dptr->wcard);
282 string_set(&dptr->path,"");
283 SAFE_FREE(dptr);
286 /****************************************************************************
287 Close a dptr given a key.
288 ****************************************************************************/
290 void dptr_close(struct smbd_server_connection *sconn, int *key)
292 struct dptr_struct *dptr;
294 if(*key == INVALID_DPTR_KEY)
295 return;
297 /* OS/2 seems to use -1 to indicate "close all directories" */
298 if (*key == -1) {
299 struct dptr_struct *next;
300 for(dptr = sconn->searches.dirptrs; dptr; dptr = next) {
301 next = dptr->next;
302 dptr_close_internal(dptr);
304 *key = INVALID_DPTR_KEY;
305 return;
308 dptr = dptr_get(sconn, *key, true);
310 if (!dptr) {
311 DEBUG(0,("Invalid key %d given to dptr_close\n", *key));
312 return;
315 dptr_close_internal(dptr);
317 *key = INVALID_DPTR_KEY;
320 /****************************************************************************
321 Close all dptrs for a cnum.
322 ****************************************************************************/
324 void dptr_closecnum(connection_struct *conn)
326 struct dptr_struct *dptr, *next;
327 struct smbd_server_connection *sconn = conn->sconn;
329 if (sconn == NULL) {
330 return;
333 for(dptr = sconn->searches.dirptrs; dptr; dptr = next) {
334 next = dptr->next;
335 if (dptr->conn == conn) {
336 dptr_close_internal(dptr);
341 /****************************************************************************
342 Idle all dptrs for a cnum.
343 ****************************************************************************/
345 void dptr_idlecnum(connection_struct *conn)
347 struct dptr_struct *dptr;
348 struct smbd_server_connection *sconn = conn->sconn;
350 if (sconn == NULL) {
351 return;
354 for(dptr = sconn->searches.dirptrs; dptr; dptr = dptr->next) {
355 if (dptr->conn == conn && dptr->dir_hnd) {
356 dptr_idle(dptr);
361 /****************************************************************************
362 Close a dptr that matches a given path, only if it matches the spid also.
363 ****************************************************************************/
365 void dptr_closepath(struct smbd_server_connection *sconn,
366 char *path,uint16 spid)
368 struct dptr_struct *dptr, *next;
369 for(dptr = sconn->searches.dirptrs; dptr; dptr = next) {
370 next = dptr->next;
371 if (spid == dptr->spid && strequal(dptr->path,path))
372 dptr_close_internal(dptr);
376 /****************************************************************************
377 Try and close the oldest handle not marked for
378 expect close in the hope that the client has
379 finished with that one.
380 ****************************************************************************/
382 static void dptr_close_oldest(struct smbd_server_connection *sconn,
383 bool old)
385 struct dptr_struct *dptr;
388 * Go to the end of the list.
390 for(dptr = sconn->searches.dirptrs; dptr && dptr->next; dptr = dptr->next)
393 if(!dptr) {
394 DEBUG(0,("No old dptrs available to close oldest ?\n"));
395 return;
399 * If 'old' is true, close the oldest oldhandle dnum (ie. 1 < dnum < 256) that
400 * does not have expect_close set. If 'old' is false, close
401 * one of the new dnum handles.
404 for(; dptr; dptr = DLIST_PREV(dptr)) {
405 if ((old && (dptr->dnum < 256) && !dptr->expect_close) ||
406 (!old && (dptr->dnum > 255))) {
407 dptr_close_internal(dptr);
408 return;
413 /****************************************************************************
414 Create a new dir ptr. If the flag old_handle is true then we must allocate
415 from the bitmap range 0 - 255 as old SMBsearch directory handles are only
416 one byte long. If old_handle is false we allocate from the range
417 256 - MAX_DIRECTORY_HANDLES. We bias the number we return by 1 to ensure
418 a directory handle is never zero.
419 wcard must not be zero.
420 ****************************************************************************/
422 NTSTATUS dptr_create(connection_struct *conn, files_struct *fsp,
423 const char *path, bool old_handle, bool expect_close,uint16 spid,
424 const char *wcard, bool wcard_has_wild, uint32 attr, struct dptr_struct **dptr_ret)
426 struct smbd_server_connection *sconn = conn->sconn;
427 struct dptr_struct *dptr = NULL;
428 struct smb_Dir *dir_hnd;
429 NTSTATUS status;
431 if (fsp && fsp->is_directory && fsp->fh->fd != -1) {
432 path = fsp->fsp_name->base_name;
435 DEBUG(5,("dptr_create dir=%s\n", path));
437 if (sconn == NULL) {
438 DEBUG(0,("dptr_create: called with fake connection_struct\n"));
439 return NT_STATUS_INTERNAL_ERROR;
442 if (!wcard) {
443 return NT_STATUS_INVALID_PARAMETER;
446 if (fsp) {
447 dir_hnd = OpenDir_fsp(NULL, conn, fsp, wcard, attr);
448 } else {
449 status = check_name(conn,path);
450 if (!NT_STATUS_IS_OK(status)) {
451 return status;
453 dir_hnd = OpenDir(NULL, conn, path, wcard, attr);
456 if (!dir_hnd) {
457 return map_nt_error_from_unix(errno);
460 if (sconn->searches.dirhandles_open >= MAX_OPEN_DIRECTORIES) {
461 dptr_idleoldest(sconn);
464 dptr = SMB_MALLOC_P(struct dptr_struct);
465 if(!dptr) {
466 DEBUG(0,("malloc fail in dptr_create.\n"));
467 TALLOC_FREE(dir_hnd);
468 return NT_STATUS_NO_MEMORY;
471 ZERO_STRUCTP(dptr);
473 if(old_handle) {
476 * This is an old-style SMBsearch request. Ensure the
477 * value we return will fit in the range 1-255.
480 dptr->dnum = bitmap_find(sconn->searches.dptr_bmap, 0);
482 if(dptr->dnum == -1 || dptr->dnum > 254) {
485 * Try and close the oldest handle not marked for
486 * expect close in the hope that the client has
487 * finished with that one.
490 dptr_close_oldest(sconn, true);
492 /* Now try again... */
493 dptr->dnum = bitmap_find(sconn->searches.dptr_bmap, 0);
494 if(dptr->dnum == -1 || dptr->dnum > 254) {
495 DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr->dnum));
496 SAFE_FREE(dptr);
497 TALLOC_FREE(dir_hnd);
498 return NT_STATUS_TOO_MANY_OPENED_FILES;
501 } else {
504 * This is a new-style trans2 request. Allocate from
505 * a range that will return 256 - MAX_DIRECTORY_HANDLES.
508 dptr->dnum = bitmap_find(sconn->searches.dptr_bmap, 255);
510 if(dptr->dnum == -1 || dptr->dnum < 255) {
513 * Try and close the oldest handle close in the hope that
514 * the client has finished with that one. This will only
515 * happen in the case of the Win98 client bug where it leaks
516 * directory handles.
519 dptr_close_oldest(sconn, false);
521 /* Now try again... */
522 dptr->dnum = bitmap_find(sconn->searches.dptr_bmap, 255);
524 if(dptr->dnum == -1 || dptr->dnum < 255) {
525 DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr->dnum));
526 SAFE_FREE(dptr);
527 TALLOC_FREE(dir_hnd);
528 return NT_STATUS_TOO_MANY_OPENED_FILES;
533 bitmap_set(sconn->searches.dptr_bmap, dptr->dnum);
535 dptr->dnum += 1; /* Always bias the dnum by one - no zero dnums allowed. */
537 string_set(&dptr->path,path);
538 dptr->conn = conn;
539 dptr->dir_hnd = dir_hnd;
540 dptr->spid = spid;
541 dptr->expect_close = expect_close;
542 dptr->wcard = SMB_STRDUP(wcard);
543 if (!dptr->wcard) {
544 bitmap_clear(sconn->searches.dptr_bmap, dptr->dnum - 1);
545 SAFE_FREE(dptr);
546 TALLOC_FREE(dir_hnd);
547 return NT_STATUS_NO_MEMORY;
549 if (lp_posix_pathnames() || (wcard[0] == '.' && wcard[1] == 0)) {
550 dptr->has_wild = True;
551 } else {
552 dptr->has_wild = wcard_has_wild;
555 dptr->attr = attr;
557 DLIST_ADD(sconn->searches.dirptrs, dptr);
559 DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n",
560 dptr->dnum,path,expect_close));
562 *dptr_ret = dptr;
564 return NT_STATUS_OK;
568 /****************************************************************************
569 Wrapper functions to access the lower level directory handles.
570 ****************************************************************************/
572 void dptr_CloseDir(files_struct *fsp)
574 if (fsp->dptr) {
576 * Ugly hack. We have defined fdopendir to return ENOSYS if dirfd also isn't
577 * present. I hate Solaris. JRA.
579 #ifdef HAVE_DIRFD
580 if (fsp->fh->fd != -1 &&
581 fsp->dptr->dir_hnd &&
582 dirfd(fsp->dptr->dir_hnd->dir)) {
583 /* The call below closes the underlying fd. */
584 fsp->fh->fd = -1;
586 #endif
587 dptr_close_internal(fsp->dptr);
588 fsp->dptr = NULL;
592 void dptr_SeekDir(struct dptr_struct *dptr, long offset)
594 SeekDir(dptr->dir_hnd, offset);
597 long dptr_TellDir(struct dptr_struct *dptr)
599 return TellDir(dptr->dir_hnd);
602 bool dptr_has_wild(struct dptr_struct *dptr)
604 return dptr->has_wild;
607 int dptr_dnum(struct dptr_struct *dptr)
609 return dptr->dnum;
612 /****************************************************************************
613 Return the next visible file name, skipping veto'd and invisible files.
614 ****************************************************************************/
616 static const char *dptr_normal_ReadDirName(struct dptr_struct *dptr,
617 long *poffset, SMB_STRUCT_STAT *pst,
618 char **ptalloced)
620 /* Normal search for the next file. */
621 const char *name;
622 char *talloced = NULL;
624 while ((name = ReadDirName(dptr->dir_hnd, poffset, pst, &talloced))
625 != NULL) {
626 if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) {
627 *ptalloced = talloced;
628 return name;
630 TALLOC_FREE(talloced);
632 return NULL;
635 /****************************************************************************
636 Return the next visible file name, skipping veto'd and invisible files.
637 ****************************************************************************/
639 char *dptr_ReadDirName(TALLOC_CTX *ctx,
640 struct dptr_struct *dptr,
641 long *poffset,
642 SMB_STRUCT_STAT *pst)
644 struct smb_filename smb_fname_base;
645 char *name = NULL;
646 const char *name_temp = NULL;
647 char *talloced = NULL;
648 char *pathreal = NULL;
649 char *found_name = NULL;
650 int ret;
652 SET_STAT_INVALID(*pst);
654 if (dptr->has_wild || dptr->did_stat) {
655 name_temp = dptr_normal_ReadDirName(dptr, poffset, pst,
656 &talloced);
657 if (name_temp == NULL) {
658 return NULL;
660 if (talloced != NULL) {
661 return talloc_move(ctx, &talloced);
663 return talloc_strdup(ctx, name_temp);
666 /* If poffset is -1 then we know we returned this name before and we
667 * have no wildcards. We're at the end of the directory. */
668 if (*poffset == END_OF_DIRECTORY_OFFSET) {
669 return NULL;
672 /* We know the stored wcard contains no wildcard characters.
673 * See if we can match with a stat call. If we can't, then set
674 * did_stat to true to ensure we only do this once and keep
675 * searching. */
677 dptr->did_stat = true;
679 /* First check if it should be visible. */
680 if (!is_visible_file(dptr->conn, dptr->path, dptr->wcard,
681 pst, true))
683 /* This only returns false if the file was found, but
684 is explicitly not visible. Set us to end of
685 directory, but return NULL as we know we can't ever
686 find it. */
687 goto ret;
690 if (VALID_STAT(*pst)) {
691 name = talloc_strdup(ctx, dptr->wcard);
692 goto ret;
695 pathreal = talloc_asprintf(ctx,
696 "%s/%s",
697 dptr->path,
698 dptr->wcard);
699 if (!pathreal)
700 return NULL;
702 /* Create an smb_filename with stream_name == NULL. */
703 ZERO_STRUCT(smb_fname_base);
704 smb_fname_base.base_name = pathreal;
706 if (SMB_VFS_STAT(dptr->conn, &smb_fname_base) == 0) {
707 *pst = smb_fname_base.st;
708 name = talloc_strdup(ctx, dptr->wcard);
709 goto clean;
710 } else {
711 /* If we get any other error than ENOENT or ENOTDIR
712 then the file exists we just can't stat it. */
713 if (errno != ENOENT && errno != ENOTDIR) {
714 name = talloc_strdup(ctx, dptr->wcard);
715 goto clean;
719 /* Stat failed. We know this is authoratiative if we are
720 * providing case sensitive semantics or the underlying
721 * filesystem is case sensitive.
723 if (dptr->conn->case_sensitive ||
724 !(dptr->conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH))
726 goto clean;
730 * Try case-insensitive stat if the fs has the ability. This avoids
731 * scanning the whole directory.
733 ret = SMB_VFS_GET_REAL_FILENAME(dptr->conn, dptr->path, dptr->wcard,
734 ctx, &found_name);
735 if (ret == 0) {
736 name = found_name;
737 goto clean;
738 } else if (errno == ENOENT) {
739 /* The case-insensitive lookup was authoritative. */
740 goto clean;
743 TALLOC_FREE(pathreal);
745 name_temp = dptr_normal_ReadDirName(dptr, poffset, pst, &talloced);
746 if (name_temp == NULL) {
747 return NULL;
749 if (talloced != NULL) {
750 return talloc_move(ctx, &talloced);
752 return talloc_strdup(ctx, name_temp);
754 clean:
755 TALLOC_FREE(pathreal);
756 ret:
757 /* We need to set the underlying dir_hnd offset to -1
758 * also as this function is usually called with the
759 * output from TellDir. */
760 dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
761 return name;
764 /****************************************************************************
765 Search for a file by name, skipping veto'ed and not visible files.
766 ****************************************************************************/
768 bool dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, SMB_STRUCT_STAT *pst)
770 SET_STAT_INVALID(*pst);
772 if (!dptr->has_wild && (dptr->dir_hnd->offset == END_OF_DIRECTORY_OFFSET)) {
773 /* This is a singleton directory and we're already at the end. */
774 *poffset = END_OF_DIRECTORY_OFFSET;
775 return False;
778 return SearchDir(dptr->dir_hnd, name, poffset);
781 /****************************************************************************
782 Add the name we're returning into the underlying cache.
783 ****************************************************************************/
785 void dptr_DirCacheAdd(struct dptr_struct *dptr, const char *name, long offset)
787 DirCacheAdd(dptr->dir_hnd, name, offset);
790 /****************************************************************************
791 Initialize variables & state data at the beginning of all search SMB requests.
792 ****************************************************************************/
793 void dptr_init_search_op(struct dptr_struct *dptr)
795 SMB_VFS_INIT_SEARCH_OP(dptr->conn, dptr->dir_hnd->dir);
798 /****************************************************************************
799 Fill the 5 byte server reserved dptr field.
800 ****************************************************************************/
802 bool dptr_fill(struct smbd_server_connection *sconn,
803 char *buf1,unsigned int key)
805 unsigned char *buf = (unsigned char *)buf1;
806 struct dptr_struct *dptr = dptr_get(sconn, key, false);
807 uint32 offset;
808 if (!dptr) {
809 DEBUG(1,("filling null dirptr %d\n",key));
810 return(False);
812 offset = (uint32)TellDir(dptr->dir_hnd);
813 DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key,
814 (long)dptr->dir_hnd,(int)offset));
815 buf[0] = key;
816 SIVAL(buf,1,offset);
817 return(True);
820 /****************************************************************************
821 Fetch the dir ptr and seek it given the 5 byte server field.
822 ****************************************************************************/
824 struct dptr_struct *dptr_fetch(struct smbd_server_connection *sconn,
825 char *buf, int *num)
827 unsigned int key = *(unsigned char *)buf;
828 struct dptr_struct *dptr = dptr_get(sconn, key, false);
829 uint32 offset;
830 long seekoff;
832 if (!dptr) {
833 DEBUG(3,("fetched null dirptr %d\n",key));
834 return(NULL);
836 *num = key;
837 offset = IVAL(buf,1);
838 if (offset == (uint32)-1) {
839 seekoff = END_OF_DIRECTORY_OFFSET;
840 } else {
841 seekoff = (long)offset;
843 SeekDir(dptr->dir_hnd,seekoff);
844 DEBUG(3,("fetching dirptr %d for path %s at offset %d\n",
845 key, dptr->path, (int)seekoff));
846 return(dptr);
849 /****************************************************************************
850 Fetch the dir ptr.
851 ****************************************************************************/
853 struct dptr_struct *dptr_fetch_lanman2(struct smbd_server_connection *sconn,
854 int dptr_num)
856 struct dptr_struct *dptr = dptr_get(sconn, dptr_num, false);
858 if (!dptr) {
859 DEBUG(3,("fetched null dirptr %d\n",dptr_num));
860 return(NULL);
862 DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr->path));
863 return(dptr);
866 /****************************************************************************
867 Check that a file matches a particular file type.
868 ****************************************************************************/
870 bool dir_check_ftype(connection_struct *conn, uint32 mode, uint32 dirtype)
872 uint32 mask;
874 /* Check the "may have" search bits. */
875 if (((mode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY)) != 0)
876 return False;
878 /* Check the "must have" bits, which are the may have bits shifted eight */
879 /* If must have bit is set, the file/dir can not be returned in search unless the matching
880 file attribute is set */
881 mask = ((dirtype >> 8) & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)); /* & 0x37 */
882 if(mask) {
883 if((mask & (mode & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM))) == mask) /* check if matching attribute present */
884 return True;
885 else
886 return False;
889 return True;
892 static bool mangle_mask_match(connection_struct *conn,
893 const char *filename,
894 const char *mask)
896 char mname[13];
898 if (!name_to_8_3(filename,mname,False,conn->params)) {
899 return False;
901 return mask_match_search(mname,mask,False);
904 bool smbd_dirptr_get_entry(TALLOC_CTX *ctx,
905 struct dptr_struct *dirptr,
906 const char *mask,
907 uint32_t dirtype,
908 bool dont_descend,
909 bool ask_sharemode,
910 bool (*match_fn)(TALLOC_CTX *ctx,
911 void *private_data,
912 const char *dname,
913 const char *mask,
914 char **_fname),
915 bool (*mode_fn)(TALLOC_CTX *ctx,
916 void *private_data,
917 struct smb_filename *smb_fname,
918 uint32_t *_mode),
919 void *private_data,
920 char **_fname,
921 struct smb_filename **_smb_fname,
922 uint32_t *_mode,
923 long *_prev_offset)
925 connection_struct *conn = dirptr->conn;
926 bool needslash;
928 *_smb_fname = NULL;
929 *_mode = 0;
931 needslash = ( dirptr->path[strlen(dirptr->path) -1] != '/');
933 while (true) {
934 long cur_offset;
935 long prev_offset;
936 SMB_STRUCT_STAT sbuf;
937 char *dname = NULL;
938 bool isdots;
939 char *fname = NULL;
940 char *pathreal = NULL;
941 struct smb_filename smb_fname;
942 uint32_t mode = 0;
943 bool ok;
944 NTSTATUS status;
946 cur_offset = dptr_TellDir(dirptr);
947 prev_offset = cur_offset;
948 dname = dptr_ReadDirName(ctx, dirptr, &cur_offset, &sbuf);
950 DEBUG(6,("smbd_dirptr_get_entry: dirptr 0x%lx now at offset %ld\n",
951 (long)dirptr, cur_offset));
953 if (dname == NULL) {
954 return false;
957 isdots = (ISDOT(dname) || ISDOTDOT(dname));
958 if (dont_descend && !isdots) {
959 TALLOC_FREE(dname);
960 continue;
964 * fname may get mangled, dname is never mangled.
965 * Whenever we're accessing the filesystem we use
966 * pathreal which is composed from dname.
969 ok = match_fn(ctx, private_data, dname, mask, &fname);
970 if (!ok) {
971 TALLOC_FREE(dname);
972 continue;
975 pathreal = talloc_asprintf(ctx, "%s%s%s",
976 dirptr->path,
977 needslash?"/":"",
978 dname);
979 if (!pathreal) {
980 TALLOC_FREE(dname);
981 TALLOC_FREE(fname);
982 return false;
985 /* Create smb_fname with NULL stream_name. */
986 ZERO_STRUCT(smb_fname);
987 smb_fname.base_name = pathreal;
988 smb_fname.st = sbuf;
990 ok = mode_fn(ctx, private_data, &smb_fname, &mode);
991 if (!ok) {
992 TALLOC_FREE(dname);
993 TALLOC_FREE(fname);
994 TALLOC_FREE(pathreal);
995 continue;
998 if (!dir_check_ftype(conn, mode, dirtype)) {
999 DEBUG(5,("[%s] attribs 0x%x didn't match 0x%x\n",
1000 fname, (unsigned int)mode, (unsigned int)dirtype));
1001 TALLOC_FREE(dname);
1002 TALLOC_FREE(fname);
1003 TALLOC_FREE(pathreal);
1004 continue;
1007 if (ask_sharemode) {
1008 struct timespec write_time_ts;
1009 struct file_id fileid;
1011 fileid = vfs_file_id_from_sbuf(conn,
1012 &smb_fname.st);
1013 get_file_infos(fileid, 0, NULL, &write_time_ts);
1014 if (!null_timespec(write_time_ts)) {
1015 update_stat_ex_mtime(&smb_fname.st,
1016 write_time_ts);
1020 DEBUG(3,("smbd_dirptr_get_entry mask=[%s] found %s "
1021 "fname=%s (%s)\n",
1022 mask, smb_fname_str_dbg(&smb_fname),
1023 dname, fname));
1025 DirCacheAdd(dirptr->dir_hnd, dname, cur_offset);
1027 TALLOC_FREE(dname);
1029 status = copy_smb_filename(ctx, &smb_fname, _smb_fname);
1030 TALLOC_FREE(pathreal);
1031 if (!NT_STATUS_IS_OK(status)) {
1032 return false;
1034 *_fname = fname;
1035 *_mode = mode;
1036 *_prev_offset = prev_offset;
1038 return true;
1041 return false;
1044 /****************************************************************************
1045 Get an 8.3 directory entry.
1046 ****************************************************************************/
1048 static bool smbd_dirptr_8_3_match_fn(TALLOC_CTX *ctx,
1049 void *private_data,
1050 const char *dname,
1051 const char *mask,
1052 char **_fname)
1054 connection_struct *conn = (connection_struct *)private_data;
1056 if ((strcmp(mask,"*.*") == 0) ||
1057 mask_match_search(dname, mask, false) ||
1058 mangle_mask_match(conn, dname, mask)) {
1059 char mname[13];
1060 const char *fname;
1062 if (!mangle_is_8_3(dname, false, conn->params)) {
1063 bool ok = name_to_8_3(dname, mname, false,
1064 conn->params);
1065 if (!ok) {
1066 return false;
1068 fname = mname;
1069 } else {
1070 fname = dname;
1073 *_fname = talloc_strdup(ctx, fname);
1074 if (*_fname == NULL) {
1075 return false;
1078 return true;
1081 return false;
1084 static bool smbd_dirptr_8_3_mode_fn(TALLOC_CTX *ctx,
1085 void *private_data,
1086 struct smb_filename *smb_fname,
1087 uint32_t *_mode)
1089 connection_struct *conn = (connection_struct *)private_data;
1091 if (!VALID_STAT(smb_fname->st)) {
1092 if ((SMB_VFS_STAT(conn, smb_fname)) != 0) {
1093 DEBUG(5,("smbd_dirptr_8_3_mode_fn: "
1094 "Couldn't stat [%s]. Error "
1095 "= %s\n",
1096 smb_fname_str_dbg(smb_fname),
1097 strerror(errno)));
1098 return false;
1102 *_mode = dos_mode(conn, smb_fname);
1103 return true;
1106 bool get_dir_entry(TALLOC_CTX *ctx,
1107 struct dptr_struct *dirptr,
1108 const char *mask,
1109 uint32_t dirtype,
1110 char **_fname,
1111 SMB_OFF_T *_size,
1112 uint32_t *_mode,
1113 struct timespec *_date,
1114 bool check_descend,
1115 bool ask_sharemode)
1117 connection_struct *conn = dirptr->conn;
1118 char *fname = NULL;
1119 struct smb_filename *smb_fname = NULL;
1120 uint32_t mode = 0;
1121 long prev_offset;
1122 bool ok;
1124 ok = smbd_dirptr_get_entry(ctx,
1125 dirptr,
1126 mask,
1127 dirtype,
1128 check_descend,
1129 ask_sharemode,
1130 smbd_dirptr_8_3_match_fn,
1131 smbd_dirptr_8_3_mode_fn,
1132 conn,
1133 &fname,
1134 &smb_fname,
1135 &mode,
1136 &prev_offset);
1137 if (!ok) {
1138 return false;
1141 *_fname = talloc_move(ctx, &fname);
1142 *_size = smb_fname->st.st_ex_size;
1143 *_mode = mode;
1144 *_date = smb_fname->st.st_ex_mtime;
1145 TALLOC_FREE(smb_fname);
1146 return true;
1149 /*******************************************************************
1150 Check to see if a user can read a file. This is only approximate,
1151 it is used as part of the "hide unreadable" option. Don't
1152 use it for anything security sensitive.
1153 ********************************************************************/
1155 static bool user_can_read_file(connection_struct *conn,
1156 struct smb_filename *smb_fname)
1159 * Never hide files from the root user.
1160 * We use (uid_t)0 here not sec_initial_uid()
1161 * as make test uses a single user context.
1164 if (get_current_uid(conn) == (uid_t)0) {
1165 return True;
1168 return can_access_file_acl(conn, smb_fname, FILE_READ_DATA);
1171 /*******************************************************************
1172 Check to see if a user can write a file (and only files, we do not
1173 check dirs on this one). This is only approximate,
1174 it is used as part of the "hide unwriteable" option. Don't
1175 use it for anything security sensitive.
1176 ********************************************************************/
1178 static bool user_can_write_file(connection_struct *conn,
1179 const struct smb_filename *smb_fname)
1182 * Never hide files from the root user.
1183 * We use (uid_t)0 here not sec_initial_uid()
1184 * as make test uses a single user context.
1187 if (get_current_uid(conn) == (uid_t)0) {
1188 return True;
1191 SMB_ASSERT(VALID_STAT(smb_fname->st));
1193 /* Pseudo-open the file */
1195 if(S_ISDIR(smb_fname->st.st_ex_mode)) {
1196 return True;
1199 return can_write_to_file(conn, smb_fname);
1202 /*******************************************************************
1203 Is a file a "special" type ?
1204 ********************************************************************/
1206 static bool file_is_special(connection_struct *conn,
1207 const struct smb_filename *smb_fname)
1210 * Never hide files from the root user.
1211 * We use (uid_t)0 here not sec_initial_uid()
1212 * as make test uses a single user context.
1215 if (get_current_uid(conn) == (uid_t)0) {
1216 return False;
1219 SMB_ASSERT(VALID_STAT(smb_fname->st));
1221 if (S_ISREG(smb_fname->st.st_ex_mode) ||
1222 S_ISDIR(smb_fname->st.st_ex_mode) ||
1223 S_ISLNK(smb_fname->st.st_ex_mode))
1224 return False;
1226 return True;
1229 /*******************************************************************
1230 Should the file be seen by the client?
1231 NOTE: A successful return is no guarantee of the file's existence.
1232 ********************************************************************/
1234 bool is_visible_file(connection_struct *conn, const char *dir_path,
1235 const char *name, SMB_STRUCT_STAT *pst, bool use_veto)
1237 bool hide_unreadable = lp_hideunreadable(SNUM(conn));
1238 bool hide_unwriteable = lp_hideunwriteable_files(SNUM(conn));
1239 bool hide_special = lp_hide_special_files(SNUM(conn));
1240 char *entry = NULL;
1241 struct smb_filename *smb_fname_base = NULL;
1242 NTSTATUS status;
1243 bool ret = false;
1245 if ((strcmp(".",name) == 0) || (strcmp("..",name) == 0)) {
1246 return True; /* . and .. are always visible. */
1249 /* If it's a vetoed file, pretend it doesn't even exist */
1250 if (use_veto && IS_VETO_PATH(conn, name)) {
1251 DEBUG(10,("is_visible_file: file %s is vetoed.\n", name ));
1252 return False;
1255 if (hide_unreadable || hide_unwriteable || hide_special) {
1256 entry = talloc_asprintf(talloc_tos(), "%s/%s", dir_path, name);
1257 if (!entry) {
1258 ret = false;
1259 goto out;
1262 /* Create an smb_filename with stream_name == NULL. */
1263 status = create_synthetic_smb_fname(talloc_tos(), entry, NULL,
1264 pst, &smb_fname_base);
1265 if (!NT_STATUS_IS_OK(status)) {
1266 ret = false;
1267 goto out;
1270 /* If the file name does not exist, there's no point checking
1271 * the configuration options. We succeed, on the basis that the
1272 * checks *might* have passed if the file was present.
1274 if (!VALID_STAT(*pst)) {
1275 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
1276 ret = true;
1277 goto out;
1278 } else {
1279 *pst = smb_fname_base->st;
1283 /* Honour _hide unreadable_ option */
1284 if (hide_unreadable &&
1285 !user_can_read_file(conn, smb_fname_base)) {
1286 DEBUG(10,("is_visible_file: file %s is unreadable.\n",
1287 entry ));
1288 ret = false;
1289 goto out;
1291 /* Honour _hide unwriteable_ option */
1292 if (hide_unwriteable && !user_can_write_file(conn,
1293 smb_fname_base)) {
1294 DEBUG(10,("is_visible_file: file %s is unwritable.\n",
1295 entry ));
1296 ret = false;
1297 goto out;
1299 /* Honour _hide_special_ option */
1300 if (hide_special && file_is_special(conn, smb_fname_base)) {
1301 DEBUG(10,("is_visible_file: file %s is special.\n",
1302 entry ));
1303 ret = false;
1304 goto out;
1308 ret = true;
1309 out:
1310 TALLOC_FREE(smb_fname_base);
1311 TALLOC_FREE(entry);
1312 return ret;
1315 static int smb_Dir_destructor(struct smb_Dir *dirp)
1317 if (dirp->dir) {
1318 #ifdef HAVE_DIRFD
1319 if (dirp->conn->sconn) {
1320 files_struct *fsp = file_find_fd(dirp->conn->sconn,
1321 dirfd(dirp->dir));
1322 if (fsp) {
1323 /* The call below closes the underlying fd. */
1324 fsp->fh->fd = -1;
1327 #endif
1328 SMB_VFS_CLOSEDIR(dirp->conn,dirp->dir);
1330 if (dirp->conn->sconn) {
1331 dirp->conn->sconn->searches.dirhandles_open--;
1333 return 0;
1336 /*******************************************************************
1337 Open a directory.
1338 ********************************************************************/
1340 struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn,
1341 const char *name,
1342 const char *mask,
1343 uint32 attr)
1345 struct smb_Dir *dirp = TALLOC_ZERO_P(mem_ctx, struct smb_Dir);
1346 struct smbd_server_connection *sconn = conn->sconn;
1348 if (!dirp) {
1349 return NULL;
1352 dirp->conn = conn;
1353 dirp->name_cache_size = lp_directory_name_cache_size(SNUM(conn));
1355 dirp->dir_path = talloc_strdup(dirp, name);
1356 if (!dirp->dir_path) {
1357 errno = ENOMEM;
1358 goto fail;
1361 if (sconn) {
1362 sconn->searches.dirhandles_open++;
1364 talloc_set_destructor(dirp, smb_Dir_destructor);
1366 dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path, mask, attr);
1367 if (!dirp->dir) {
1368 DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp->dir_path,
1369 strerror(errno) ));
1370 goto fail;
1373 return dirp;
1375 fail:
1376 TALLOC_FREE(dirp);
1377 return NULL;
1380 /*******************************************************************
1381 Open a directory from an fsp.
1382 ********************************************************************/
1384 static struct smb_Dir *OpenDir_fsp(TALLOC_CTX *mem_ctx, connection_struct *conn,
1385 files_struct *fsp,
1386 const char *mask,
1387 uint32 attr)
1389 struct smb_Dir *dirp = TALLOC_ZERO_P(mem_ctx, struct smb_Dir);
1390 struct smbd_server_connection *sconn = conn->sconn;
1392 if (!dirp) {
1393 return NULL;
1396 dirp->conn = conn;
1397 dirp->name_cache_size = lp_directory_name_cache_size(SNUM(conn));
1399 dirp->dir_path = talloc_strdup(dirp, fsp->fsp_name->base_name);
1400 if (!dirp->dir_path) {
1401 errno = ENOMEM;
1402 goto fail;
1405 if (sconn) {
1406 sconn->searches.dirhandles_open++;
1408 talloc_set_destructor(dirp, smb_Dir_destructor);
1410 if (fsp->is_directory && fsp->fh->fd != -1) {
1411 dirp->dir = SMB_VFS_FDOPENDIR(fsp, mask, attr);
1412 if (dirp->dir == NULL) {
1413 DEBUG(10,("OpenDir_fsp: SMB_VFS_FDOPENDIR on %s returned "
1414 "NULL (%s)\n",
1415 dirp->dir_path,
1416 strerror(errno)));
1417 if (errno != ENOSYS) {
1418 return NULL;
1423 if (dirp->dir == NULL) {
1424 /* FDOPENDIR didn't work. Use OPENDIR instead. */
1425 dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path, mask, attr);
1428 if (!dirp->dir) {
1429 DEBUG(5,("OpenDir_fsp: Can't open %s. %s\n", dirp->dir_path,
1430 strerror(errno) ));
1431 goto fail;
1434 return dirp;
1436 fail:
1437 TALLOC_FREE(dirp);
1438 return NULL;
1442 /*******************************************************************
1443 Read from a directory.
1444 Return directory entry, current offset, and optional stat information.
1445 Don't check for veto or invisible files.
1446 ********************************************************************/
1448 const char *ReadDirName(struct smb_Dir *dirp, long *poffset,
1449 SMB_STRUCT_STAT *sbuf, char **ptalloced)
1451 const char *n;
1452 char *talloced = NULL;
1453 connection_struct *conn = dirp->conn;
1455 /* Cheat to allow . and .. to be the first entries returned. */
1456 if (((*poffset == START_OF_DIRECTORY_OFFSET) ||
1457 (*poffset == DOT_DOT_DIRECTORY_OFFSET)) && (dirp->file_number < 2))
1459 if (dirp->file_number == 0) {
1460 n = ".";
1461 *poffset = dirp->offset = START_OF_DIRECTORY_OFFSET;
1462 } else {
1463 n = "..";
1464 *poffset = dirp->offset = DOT_DOT_DIRECTORY_OFFSET;
1466 dirp->file_number++;
1467 *ptalloced = NULL;
1468 return n;
1469 } else if (*poffset == END_OF_DIRECTORY_OFFSET) {
1470 *poffset = dirp->offset = END_OF_DIRECTORY_OFFSET;
1471 return NULL;
1472 } else {
1473 /* A real offset, seek to it. */
1474 SeekDir(dirp, *poffset);
1477 while ((n = vfs_readdirname(conn, dirp->dir, sbuf, &talloced))) {
1478 /* Ignore . and .. - we've already returned them. */
1479 if (*n == '.') {
1480 if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
1481 TALLOC_FREE(talloced);
1482 continue;
1485 *poffset = dirp->offset = SMB_VFS_TELLDIR(conn, dirp->dir);
1486 *ptalloced = talloced;
1487 dirp->file_number++;
1488 return n;
1490 *poffset = dirp->offset = END_OF_DIRECTORY_OFFSET;
1491 *ptalloced = NULL;
1492 return NULL;
1495 /*******************************************************************
1496 Rewind to the start.
1497 ********************************************************************/
1499 void RewindDir(struct smb_Dir *dirp, long *poffset)
1501 SMB_VFS_REWINDDIR(dirp->conn, dirp->dir);
1502 dirp->file_number = 0;
1503 dirp->offset = START_OF_DIRECTORY_OFFSET;
1504 *poffset = START_OF_DIRECTORY_OFFSET;
1507 /*******************************************************************
1508 Seek a dir.
1509 ********************************************************************/
1511 void SeekDir(struct smb_Dir *dirp, long offset)
1513 if (offset != dirp->offset) {
1514 if (offset == START_OF_DIRECTORY_OFFSET) {
1515 RewindDir(dirp, &offset);
1517 * Ok we should really set the file number here
1518 * to 1 to enable ".." to be returned next. Trouble
1519 * is I'm worried about callers using SeekDir(dirp,0)
1520 * as equivalent to RewindDir(). So leave this alone
1521 * for now.
1523 } else if (offset == DOT_DOT_DIRECTORY_OFFSET) {
1524 RewindDir(dirp, &offset);
1526 * Set the file number to 2 - we want to get the first
1527 * real file entry (the one we return after "..")
1528 * on the next ReadDir.
1530 dirp->file_number = 2;
1531 } else if (offset == END_OF_DIRECTORY_OFFSET) {
1532 ; /* Don't seek in this case. */
1533 } else {
1534 SMB_VFS_SEEKDIR(dirp->conn, dirp->dir, offset);
1536 dirp->offset = offset;
1540 /*******************************************************************
1541 Tell a dir position.
1542 ********************************************************************/
1544 long TellDir(struct smb_Dir *dirp)
1546 return(dirp->offset);
1549 /*******************************************************************
1550 Add an entry into the dcache.
1551 ********************************************************************/
1553 void DirCacheAdd(struct smb_Dir *dirp, const char *name, long offset)
1555 struct name_cache_entry *e;
1557 if (dirp->name_cache_size == 0) {
1558 return;
1561 if (dirp->name_cache == NULL) {
1562 dirp->name_cache = TALLOC_ZERO_ARRAY(
1563 dirp, struct name_cache_entry, dirp->name_cache_size);
1565 if (dirp->name_cache == NULL) {
1566 return;
1570 dirp->name_cache_index = (dirp->name_cache_index+1) %
1571 dirp->name_cache_size;
1572 e = &dirp->name_cache[dirp->name_cache_index];
1573 TALLOC_FREE(e->name);
1574 e->name = talloc_strdup(dirp, name);
1575 e->offset = offset;
1578 /*******************************************************************
1579 Find an entry by name. Leave us at the offset after it.
1580 Don't check for veto or invisible files.
1581 ********************************************************************/
1583 bool SearchDir(struct smb_Dir *dirp, const char *name, long *poffset)
1585 int i;
1586 const char *entry = NULL;
1587 char *talloced = NULL;
1588 connection_struct *conn = dirp->conn;
1590 /* Search back in the name cache. */
1591 if (dirp->name_cache_size && dirp->name_cache) {
1592 for (i = dirp->name_cache_index; i >= 0; i--) {
1593 struct name_cache_entry *e = &dirp->name_cache[i];
1594 if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1595 *poffset = e->offset;
1596 SeekDir(dirp, e->offset);
1597 return True;
1600 for (i = dirp->name_cache_size - 1; i > dirp->name_cache_index; i--) {
1601 struct name_cache_entry *e = &dirp->name_cache[i];
1602 if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1603 *poffset = e->offset;
1604 SeekDir(dirp, e->offset);
1605 return True;
1610 /* Not found in the name cache. Rewind directory and start from scratch. */
1611 SMB_VFS_REWINDDIR(conn, dirp->dir);
1612 dirp->file_number = 0;
1613 *poffset = START_OF_DIRECTORY_OFFSET;
1614 while ((entry = ReadDirName(dirp, poffset, NULL, &talloced))) {
1615 if (conn->case_sensitive ? (strcmp(entry, name) == 0) : strequal(entry, name)) {
1616 TALLOC_FREE(talloced);
1617 return True;
1619 TALLOC_FREE(talloced);
1621 return False;
1624 /*****************************************************************
1625 Is this directory empty ?
1626 *****************************************************************/
1628 NTSTATUS can_delete_directory(struct connection_struct *conn,
1629 const char *dirname)
1631 NTSTATUS status = NT_STATUS_OK;
1632 long dirpos = 0;
1633 const char *dname = NULL;
1634 char *talloced = NULL;
1635 SMB_STRUCT_STAT st;
1636 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
1637 dirname, NULL, 0);
1639 if (!dir_hnd) {
1640 return map_nt_error_from_unix(errno);
1643 while ((dname = ReadDirName(dir_hnd, &dirpos, &st, &talloced))) {
1644 /* Quick check for "." and ".." */
1645 if (dname[0] == '.') {
1646 if (!dname[1] || (dname[1] == '.' && !dname[2])) {
1647 TALLOC_FREE(talloced);
1648 continue;
1652 if (!is_visible_file(conn, dirname, dname, &st, True)) {
1653 TALLOC_FREE(talloced);
1654 continue;
1657 DEBUG(10,("can_delete_directory: got name %s - can't delete\n",
1658 dname ));
1659 status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1660 break;
1662 TALLOC_FREE(talloced);
1663 TALLOC_FREE(dir_hnd);
1665 return status;