s3:libsmb: move cli->mid to cli->smb1.mid
[Samba/vl.git] / source3 / smbd / dir.c
blobfc74eea76cdba114828743bd6dc753803eb5170d
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"
26 #include "lib/util/bitmap.h"
29 This module implements directory related functions for Samba.
32 /* "Special" directory offsets. */
33 #define END_OF_DIRECTORY_OFFSET ((long)-1)
34 #define START_OF_DIRECTORY_OFFSET ((long)0)
35 #define DOT_DOT_DIRECTORY_OFFSET ((long)0x80000000)
37 /* Make directory handle internals available. */
39 struct name_cache_entry {
40 char *name;
41 long offset;
44 struct smb_Dir {
45 connection_struct *conn;
46 SMB_STRUCT_DIR *dir;
47 long offset;
48 char *dir_path;
49 size_t name_cache_size;
50 struct name_cache_entry *name_cache;
51 unsigned int name_cache_index;
52 unsigned int file_number;
55 struct dptr_struct {
56 struct dptr_struct *next, *prev;
57 int dnum;
58 uint16 spid;
59 struct connection_struct *conn;
60 struct smb_Dir *dir_hnd;
61 bool expect_close;
62 char *wcard;
63 uint32 attr;
64 char *path;
65 bool has_wild; /* Set to true if the wcard entry has MS wildcard characters in it. */
66 bool did_stat; /* Optimisation for non-wcard searches. */
69 static struct smb_Dir *OpenDir_fsp(TALLOC_CTX *mem_ctx, connection_struct *conn,
70 files_struct *fsp,
71 const char *mask,
72 uint32 attr);
74 #define INVALID_DPTR_KEY (-3)
76 /****************************************************************************
77 Make a dir struct.
78 ****************************************************************************/
80 bool make_dir_struct(TALLOC_CTX *ctx,
81 char *buf,
82 const char *mask,
83 const char *fname,
84 SMB_OFF_T size,
85 uint32 mode,
86 time_t date,
87 bool uc)
89 char *p;
90 char *mask2 = talloc_strdup(ctx, mask);
92 if (!mask2) {
93 return False;
96 if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
97 size = 0;
100 memset(buf+1,' ',11);
101 if ((p = strchr_m(mask2,'.')) != NULL) {
102 *p = 0;
103 push_ascii(buf+1,mask2,8, 0);
104 push_ascii(buf+9,p+1,3, 0);
105 *p = '.';
106 } else {
107 push_ascii(buf+1,mask2,11, 0);
110 memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
111 SCVAL(buf,21,mode);
112 srv_put_dos_date(buf,22,date);
113 SSVAL(buf,26,size & 0xFFFF);
114 SSVAL(buf,28,(size >> 16)&0xFFFF);
115 /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf.
116 Strange, but verified on W2K3. Needed for OS/2. JRA. */
117 push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0);
118 DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname));
119 return True;
122 /****************************************************************************
123 Initialise the dir bitmap.
124 ****************************************************************************/
126 bool init_dptrs(struct smbd_server_connection *sconn)
128 if (sconn->searches.dptr_bmap) {
129 return true;
132 sconn->searches.dptr_bmap = bitmap_talloc(
133 sconn, MAX_DIRECTORY_HANDLES);
135 if (sconn->searches.dptr_bmap == NULL) {
136 return false;
139 return true;
142 /****************************************************************************
143 Idle a dptr - the directory is closed but the control info is kept.
144 ****************************************************************************/
146 static void dptr_idle(struct dptr_struct *dptr)
148 if (dptr->dir_hnd) {
149 DEBUG(4,("Idling dptr dnum %d\n",dptr->dnum));
150 TALLOC_FREE(dptr->dir_hnd);
154 /****************************************************************************
155 Idle the oldest dptr.
156 ****************************************************************************/
158 static void dptr_idleoldest(struct smbd_server_connection *sconn)
160 struct dptr_struct *dptr;
163 * Go to the end of the list.
165 dptr = DLIST_TAIL(sconn->searches.dirptrs);
167 if(!dptr) {
168 DEBUG(0,("No dptrs available to idle ?\n"));
169 return;
173 * Idle the oldest pointer.
176 for(; dptr; dptr = DLIST_PREV(dptr)) {
177 if (dptr->dir_hnd) {
178 dptr_idle(dptr);
179 return;
184 /****************************************************************************
185 Get the struct dptr_struct for a dir index.
186 ****************************************************************************/
188 static struct dptr_struct *dptr_get(struct smbd_server_connection *sconn,
189 int key, bool forclose)
191 struct dptr_struct *dptr;
193 for(dptr = sconn->searches.dirptrs; dptr; dptr = dptr->next) {
194 if(dptr->dnum == key) {
195 if (!forclose && !dptr->dir_hnd) {
196 if (sconn->searches.dirhandles_open >= MAX_OPEN_DIRECTORIES)
197 dptr_idleoldest(sconn);
198 DEBUG(4,("dptr_get: Reopening dptr key %d\n",key));
199 if (!(dptr->dir_hnd = OpenDir(
200 NULL, dptr->conn, dptr->path,
201 dptr->wcard, dptr->attr))) {
202 DEBUG(4,("dptr_get: Failed to open %s (%s)\n",dptr->path,
203 strerror(errno)));
204 return False;
207 DLIST_PROMOTE(sconn->searches.dirptrs,dptr);
208 return dptr;
211 return(NULL);
214 /****************************************************************************
215 Get the dir path for a dir index.
216 ****************************************************************************/
218 char *dptr_path(struct smbd_server_connection *sconn, int key)
220 struct dptr_struct *dptr = dptr_get(sconn, key, false);
221 if (dptr)
222 return(dptr->path);
223 return(NULL);
226 /****************************************************************************
227 Get the dir wcard for a dir index.
228 ****************************************************************************/
230 char *dptr_wcard(struct smbd_server_connection *sconn, int key)
232 struct dptr_struct *dptr = dptr_get(sconn, key, false);
233 if (dptr)
234 return(dptr->wcard);
235 return(NULL);
238 /****************************************************************************
239 Get the dir attrib for a dir index.
240 ****************************************************************************/
242 uint16 dptr_attr(struct smbd_server_connection *sconn, int key)
244 struct dptr_struct *dptr = dptr_get(sconn, key, false);
245 if (dptr)
246 return(dptr->attr);
247 return(0);
250 /****************************************************************************
251 Close a dptr (internal func).
252 ****************************************************************************/
254 static void dptr_close_internal(struct dptr_struct *dptr)
256 struct smbd_server_connection *sconn = dptr->conn->sconn;
258 DEBUG(4,("closing dptr key %d\n",dptr->dnum));
260 if (sconn == NULL) {
261 goto done;
264 DLIST_REMOVE(sconn->searches.dirptrs, dptr);
267 * Free the dnum in the bitmap. Remember the dnum value is always
268 * biased by one with respect to the bitmap.
271 if (!bitmap_query(sconn->searches.dptr_bmap, dptr->dnum - 1)) {
272 DEBUG(0,("dptr_close_internal : Error - closing dnum = %d and bitmap not set !\n",
273 dptr->dnum ));
276 bitmap_clear(sconn->searches.dptr_bmap, dptr->dnum - 1);
278 done:
279 TALLOC_FREE(dptr->dir_hnd);
281 /* Lanman 2 specific code */
282 SAFE_FREE(dptr->wcard);
283 string_set(&dptr->path,"");
284 SAFE_FREE(dptr);
287 /****************************************************************************
288 Close a dptr given a key.
289 ****************************************************************************/
291 void dptr_close(struct smbd_server_connection *sconn, int *key)
293 struct dptr_struct *dptr;
295 if(*key == INVALID_DPTR_KEY)
296 return;
298 /* OS/2 seems to use -1 to indicate "close all directories" */
299 if (*key == -1) {
300 struct dptr_struct *next;
301 for(dptr = sconn->searches.dirptrs; dptr; dptr = next) {
302 next = dptr->next;
303 dptr_close_internal(dptr);
305 *key = INVALID_DPTR_KEY;
306 return;
309 dptr = dptr_get(sconn, *key, true);
311 if (!dptr) {
312 DEBUG(0,("Invalid key %d given to dptr_close\n", *key));
313 return;
316 dptr_close_internal(dptr);
318 *key = INVALID_DPTR_KEY;
321 /****************************************************************************
322 Close all dptrs for a cnum.
323 ****************************************************************************/
325 void dptr_closecnum(connection_struct *conn)
327 struct dptr_struct *dptr, *next;
328 struct smbd_server_connection *sconn = conn->sconn;
330 if (sconn == NULL) {
331 return;
334 for(dptr = sconn->searches.dirptrs; dptr; dptr = next) {
335 next = dptr->next;
336 if (dptr->conn == conn) {
337 dptr_close_internal(dptr);
342 /****************************************************************************
343 Idle all dptrs for a cnum.
344 ****************************************************************************/
346 void dptr_idlecnum(connection_struct *conn)
348 struct dptr_struct *dptr;
349 struct smbd_server_connection *sconn = conn->sconn;
351 if (sconn == NULL) {
352 return;
355 for(dptr = sconn->searches.dirptrs; dptr; dptr = dptr->next) {
356 if (dptr->conn == conn && dptr->dir_hnd) {
357 dptr_idle(dptr);
362 /****************************************************************************
363 Close a dptr that matches a given path, only if it matches the spid also.
364 ****************************************************************************/
366 void dptr_closepath(struct smbd_server_connection *sconn,
367 char *path,uint16 spid)
369 struct dptr_struct *dptr, *next;
370 for(dptr = sconn->searches.dirptrs; dptr; dptr = next) {
371 next = dptr->next;
372 if (spid == dptr->spid && strequal(dptr->path,path))
373 dptr_close_internal(dptr);
377 /****************************************************************************
378 Try and close the oldest handle not marked for
379 expect close in the hope that the client has
380 finished with that one.
381 ****************************************************************************/
383 static void dptr_close_oldest(struct smbd_server_connection *sconn,
384 bool old)
386 struct dptr_struct *dptr;
389 * Go to the end of the list.
391 for(dptr = sconn->searches.dirptrs; dptr && dptr->next; dptr = dptr->next)
394 if(!dptr) {
395 DEBUG(0,("No old dptrs available to close oldest ?\n"));
396 return;
400 * If 'old' is true, close the oldest oldhandle dnum (ie. 1 < dnum < 256) that
401 * does not have expect_close set. If 'old' is false, close
402 * one of the new dnum handles.
405 for(; dptr; dptr = DLIST_PREV(dptr)) {
406 if ((old && (dptr->dnum < 256) && !dptr->expect_close) ||
407 (!old && (dptr->dnum > 255))) {
408 dptr_close_internal(dptr);
409 return;
414 /****************************************************************************
415 Create a new dir ptr. If the flag old_handle is true then we must allocate
416 from the bitmap range 0 - 255 as old SMBsearch directory handles are only
417 one byte long. If old_handle is false we allocate from the range
418 256 - MAX_DIRECTORY_HANDLES. We bias the number we return by 1 to ensure
419 a directory handle is never zero.
420 wcard must not be zero.
421 ****************************************************************************/
423 NTSTATUS dptr_create(connection_struct *conn, files_struct *fsp,
424 const char *path, bool old_handle, bool expect_close,uint16 spid,
425 const char *wcard, bool wcard_has_wild, uint32 attr, struct dptr_struct **dptr_ret)
427 struct smbd_server_connection *sconn = conn->sconn;
428 struct dptr_struct *dptr = NULL;
429 struct smb_Dir *dir_hnd;
430 NTSTATUS status;
432 if (fsp && fsp->is_directory && fsp->fh->fd != -1) {
433 path = fsp->fsp_name->base_name;
436 DEBUG(5,("dptr_create dir=%s\n", path));
438 if (sconn == NULL) {
439 DEBUG(0,("dptr_create: called with fake connection_struct\n"));
440 return NT_STATUS_INTERNAL_ERROR;
443 if (!wcard) {
444 return NT_STATUS_INVALID_PARAMETER;
447 if (fsp) {
448 dir_hnd = OpenDir_fsp(NULL, conn, fsp, wcard, attr);
449 } else {
450 status = check_name(conn,path);
451 if (!NT_STATUS_IS_OK(status)) {
452 return status;
454 dir_hnd = OpenDir(NULL, conn, path, wcard, attr);
457 if (!dir_hnd) {
458 return map_nt_error_from_unix(errno);
461 if (sconn->searches.dirhandles_open >= MAX_OPEN_DIRECTORIES) {
462 dptr_idleoldest(sconn);
465 dptr = SMB_MALLOC_P(struct dptr_struct);
466 if(!dptr) {
467 DEBUG(0,("malloc fail in dptr_create.\n"));
468 TALLOC_FREE(dir_hnd);
469 return NT_STATUS_NO_MEMORY;
472 ZERO_STRUCTP(dptr);
474 if(old_handle) {
477 * This is an old-style SMBsearch request. Ensure the
478 * value we return will fit in the range 1-255.
481 dptr->dnum = bitmap_find(sconn->searches.dptr_bmap, 0);
483 if(dptr->dnum == -1 || dptr->dnum > 254) {
486 * Try and close the oldest handle not marked for
487 * expect close in the hope that the client has
488 * finished with that one.
491 dptr_close_oldest(sconn, true);
493 /* Now try again... */
494 dptr->dnum = bitmap_find(sconn->searches.dptr_bmap, 0);
495 if(dptr->dnum == -1 || dptr->dnum > 254) {
496 DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr->dnum));
497 SAFE_FREE(dptr);
498 TALLOC_FREE(dir_hnd);
499 return NT_STATUS_TOO_MANY_OPENED_FILES;
502 } else {
505 * This is a new-style trans2 request. Allocate from
506 * a range that will return 256 - MAX_DIRECTORY_HANDLES.
509 dptr->dnum = bitmap_find(sconn->searches.dptr_bmap, 255);
511 if(dptr->dnum == -1 || dptr->dnum < 255) {
514 * Try and close the oldest handle close in the hope that
515 * the client has finished with that one. This will only
516 * happen in the case of the Win98 client bug where it leaks
517 * directory handles.
520 dptr_close_oldest(sconn, false);
522 /* Now try again... */
523 dptr->dnum = bitmap_find(sconn->searches.dptr_bmap, 255);
525 if(dptr->dnum == -1 || dptr->dnum < 255) {
526 DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr->dnum));
527 SAFE_FREE(dptr);
528 TALLOC_FREE(dir_hnd);
529 return NT_STATUS_TOO_MANY_OPENED_FILES;
534 bitmap_set(sconn->searches.dptr_bmap, dptr->dnum);
536 dptr->dnum += 1; /* Always bias the dnum by one - no zero dnums allowed. */
538 string_set(&dptr->path,path);
539 dptr->conn = conn;
540 dptr->dir_hnd = dir_hnd;
541 dptr->spid = spid;
542 dptr->expect_close = expect_close;
543 dptr->wcard = SMB_STRDUP(wcard);
544 if (!dptr->wcard) {
545 bitmap_clear(sconn->searches.dptr_bmap, dptr->dnum - 1);
546 SAFE_FREE(dptr);
547 TALLOC_FREE(dir_hnd);
548 return NT_STATUS_NO_MEMORY;
550 if (lp_posix_pathnames() || (wcard[0] == '.' && wcard[1] == 0)) {
551 dptr->has_wild = True;
552 } else {
553 dptr->has_wild = wcard_has_wild;
556 dptr->attr = attr;
558 DLIST_ADD(sconn->searches.dirptrs, dptr);
560 DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n",
561 dptr->dnum,path,expect_close));
563 *dptr_ret = dptr;
565 return NT_STATUS_OK;
569 /****************************************************************************
570 Wrapper functions to access the lower level directory handles.
571 ****************************************************************************/
573 void dptr_CloseDir(files_struct *fsp)
575 if (fsp->dptr) {
577 * Ugly hack. We have defined fdopendir to return ENOSYS if dirfd also isn't
578 * present. I hate Solaris. JRA.
580 #ifdef HAVE_DIRFD
581 if (fsp->fh->fd != -1 &&
582 fsp->dptr->dir_hnd &&
583 dirfd(fsp->dptr->dir_hnd->dir)) {
584 /* The call below closes the underlying fd. */
585 fsp->fh->fd = -1;
587 #endif
588 dptr_close_internal(fsp->dptr);
589 fsp->dptr = NULL;
593 void dptr_SeekDir(struct dptr_struct *dptr, long offset)
595 SeekDir(dptr->dir_hnd, offset);
598 long dptr_TellDir(struct dptr_struct *dptr)
600 return TellDir(dptr->dir_hnd);
603 bool dptr_has_wild(struct dptr_struct *dptr)
605 return dptr->has_wild;
608 int dptr_dnum(struct dptr_struct *dptr)
610 return dptr->dnum;
613 /****************************************************************************
614 Return the next visible file name, skipping veto'd and invisible files.
615 ****************************************************************************/
617 static const char *dptr_normal_ReadDirName(struct dptr_struct *dptr,
618 long *poffset, SMB_STRUCT_STAT *pst,
619 char **ptalloced)
621 /* Normal search for the next file. */
622 const char *name;
623 char *talloced = NULL;
625 while ((name = ReadDirName(dptr->dir_hnd, poffset, pst, &talloced))
626 != NULL) {
627 if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) {
628 *ptalloced = talloced;
629 return name;
631 TALLOC_FREE(talloced);
633 return NULL;
636 /****************************************************************************
637 Return the next visible file name, skipping veto'd and invisible files.
638 ****************************************************************************/
640 char *dptr_ReadDirName(TALLOC_CTX *ctx,
641 struct dptr_struct *dptr,
642 long *poffset,
643 SMB_STRUCT_STAT *pst)
645 struct smb_filename smb_fname_base;
646 char *name = NULL;
647 const char *name_temp = NULL;
648 char *talloced = NULL;
649 char *pathreal = NULL;
650 char *found_name = NULL;
651 int ret;
653 SET_STAT_INVALID(*pst);
655 if (dptr->has_wild || dptr->did_stat) {
656 name_temp = dptr_normal_ReadDirName(dptr, poffset, pst,
657 &talloced);
658 if (name_temp == NULL) {
659 return NULL;
661 if (talloced != NULL) {
662 return talloc_move(ctx, &talloced);
664 return talloc_strdup(ctx, name_temp);
667 /* If poffset is -1 then we know we returned this name before and we
668 * have no wildcards. We're at the end of the directory. */
669 if (*poffset == END_OF_DIRECTORY_OFFSET) {
670 return NULL;
673 /* We know the stored wcard contains no wildcard characters.
674 * See if we can match with a stat call. If we can't, then set
675 * did_stat to true to ensure we only do this once and keep
676 * searching. */
678 dptr->did_stat = true;
680 /* First check if it should be visible. */
681 if (!is_visible_file(dptr->conn, dptr->path, dptr->wcard,
682 pst, true))
684 /* This only returns false if the file was found, but
685 is explicitly not visible. Set us to end of
686 directory, but return NULL as we know we can't ever
687 find it. */
688 goto ret;
691 if (VALID_STAT(*pst)) {
692 name = talloc_strdup(ctx, dptr->wcard);
693 goto ret;
696 pathreal = talloc_asprintf(ctx,
697 "%s/%s",
698 dptr->path,
699 dptr->wcard);
700 if (!pathreal)
701 return NULL;
703 /* Create an smb_filename with stream_name == NULL. */
704 ZERO_STRUCT(smb_fname_base);
705 smb_fname_base.base_name = pathreal;
707 if (SMB_VFS_STAT(dptr->conn, &smb_fname_base) == 0) {
708 *pst = smb_fname_base.st;
709 name = talloc_strdup(ctx, dptr->wcard);
710 goto clean;
711 } else {
712 /* If we get any other error than ENOENT or ENOTDIR
713 then the file exists we just can't stat it. */
714 if (errno != ENOENT && errno != ENOTDIR) {
715 name = talloc_strdup(ctx, dptr->wcard);
716 goto clean;
720 /* Stat failed. We know this is authoratiative if we are
721 * providing case sensitive semantics or the underlying
722 * filesystem is case sensitive.
724 if (dptr->conn->case_sensitive ||
725 !(dptr->conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH))
727 goto clean;
731 * Try case-insensitive stat if the fs has the ability. This avoids
732 * scanning the whole directory.
734 ret = SMB_VFS_GET_REAL_FILENAME(dptr->conn, dptr->path, dptr->wcard,
735 ctx, &found_name);
736 if (ret == 0) {
737 name = found_name;
738 goto clean;
739 } else if (errno == ENOENT) {
740 /* The case-insensitive lookup was authoritative. */
741 goto clean;
744 TALLOC_FREE(pathreal);
746 name_temp = dptr_normal_ReadDirName(dptr, poffset, pst, &talloced);
747 if (name_temp == NULL) {
748 return NULL;
750 if (talloced != NULL) {
751 return talloc_move(ctx, &talloced);
753 return talloc_strdup(ctx, name_temp);
755 clean:
756 TALLOC_FREE(pathreal);
757 ret:
758 /* We need to set the underlying dir_hnd offset to -1
759 * also as this function is usually called with the
760 * output from TellDir. */
761 dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
762 return name;
765 /****************************************************************************
766 Search for a file by name, skipping veto'ed and not visible files.
767 ****************************************************************************/
769 bool dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, SMB_STRUCT_STAT *pst)
771 SET_STAT_INVALID(*pst);
773 if (!dptr->has_wild && (dptr->dir_hnd->offset == END_OF_DIRECTORY_OFFSET)) {
774 /* This is a singleton directory and we're already at the end. */
775 *poffset = END_OF_DIRECTORY_OFFSET;
776 return False;
779 return SearchDir(dptr->dir_hnd, name, poffset);
782 /****************************************************************************
783 Add the name we're returning into the underlying cache.
784 ****************************************************************************/
786 void dptr_DirCacheAdd(struct dptr_struct *dptr, const char *name, long offset)
788 DirCacheAdd(dptr->dir_hnd, name, offset);
791 /****************************************************************************
792 Initialize variables & state data at the beginning of all search SMB requests.
793 ****************************************************************************/
794 void dptr_init_search_op(struct dptr_struct *dptr)
796 SMB_VFS_INIT_SEARCH_OP(dptr->conn, dptr->dir_hnd->dir);
799 /****************************************************************************
800 Fill the 5 byte server reserved dptr field.
801 ****************************************************************************/
803 bool dptr_fill(struct smbd_server_connection *sconn,
804 char *buf1,unsigned int key)
806 unsigned char *buf = (unsigned char *)buf1;
807 struct dptr_struct *dptr = dptr_get(sconn, key, false);
808 uint32 offset;
809 if (!dptr) {
810 DEBUG(1,("filling null dirptr %d\n",key));
811 return(False);
813 offset = (uint32)TellDir(dptr->dir_hnd);
814 DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key,
815 (long)dptr->dir_hnd,(int)offset));
816 buf[0] = key;
817 SIVAL(buf,1,offset);
818 return(True);
821 /****************************************************************************
822 Fetch the dir ptr and seek it given the 5 byte server field.
823 ****************************************************************************/
825 struct dptr_struct *dptr_fetch(struct smbd_server_connection *sconn,
826 char *buf, int *num)
828 unsigned int key = *(unsigned char *)buf;
829 struct dptr_struct *dptr = dptr_get(sconn, key, false);
830 uint32 offset;
831 long seekoff;
833 if (!dptr) {
834 DEBUG(3,("fetched null dirptr %d\n",key));
835 return(NULL);
837 *num = key;
838 offset = IVAL(buf,1);
839 if (offset == (uint32)-1) {
840 seekoff = END_OF_DIRECTORY_OFFSET;
841 } else {
842 seekoff = (long)offset;
844 SeekDir(dptr->dir_hnd,seekoff);
845 DEBUG(3,("fetching dirptr %d for path %s at offset %d\n",
846 key, dptr->path, (int)seekoff));
847 return(dptr);
850 /****************************************************************************
851 Fetch the dir ptr.
852 ****************************************************************************/
854 struct dptr_struct *dptr_fetch_lanman2(struct smbd_server_connection *sconn,
855 int dptr_num)
857 struct dptr_struct *dptr = dptr_get(sconn, dptr_num, false);
859 if (!dptr) {
860 DEBUG(3,("fetched null dirptr %d\n",dptr_num));
861 return(NULL);
863 DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr->path));
864 return(dptr);
867 /****************************************************************************
868 Check that a file matches a particular file type.
869 ****************************************************************************/
871 bool dir_check_ftype(connection_struct *conn, uint32 mode, uint32 dirtype)
873 uint32 mask;
875 /* Check the "may have" search bits. */
876 if (((mode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY)) != 0)
877 return False;
879 /* Check the "must have" bits, which are the may have bits shifted eight */
880 /* If must have bit is set, the file/dir can not be returned in search unless the matching
881 file attribute is set */
882 mask = ((dirtype >> 8) & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)); /* & 0x37 */
883 if(mask) {
884 if((mask & (mode & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM))) == mask) /* check if matching attribute present */
885 return True;
886 else
887 return False;
890 return True;
893 static bool mangle_mask_match(connection_struct *conn,
894 const char *filename,
895 const char *mask)
897 char mname[13];
899 if (!name_to_8_3(filename,mname,False,conn->params)) {
900 return False;
902 return mask_match_search(mname,mask,False);
905 bool smbd_dirptr_get_entry(TALLOC_CTX *ctx,
906 struct dptr_struct *dirptr,
907 const char *mask,
908 uint32_t dirtype,
909 bool dont_descend,
910 bool ask_sharemode,
911 bool (*match_fn)(TALLOC_CTX *ctx,
912 void *private_data,
913 const char *dname,
914 const char *mask,
915 char **_fname),
916 bool (*mode_fn)(TALLOC_CTX *ctx,
917 void *private_data,
918 struct smb_filename *smb_fname,
919 uint32_t *_mode),
920 void *private_data,
921 char **_fname,
922 struct smb_filename **_smb_fname,
923 uint32_t *_mode,
924 long *_prev_offset)
926 connection_struct *conn = dirptr->conn;
927 bool needslash;
929 *_smb_fname = NULL;
930 *_mode = 0;
932 needslash = ( dirptr->path[strlen(dirptr->path) -1] != '/');
934 while (true) {
935 long cur_offset;
936 long prev_offset;
937 SMB_STRUCT_STAT sbuf;
938 char *dname = NULL;
939 bool isdots;
940 char *fname = NULL;
941 char *pathreal = NULL;
942 struct smb_filename smb_fname;
943 uint32_t mode = 0;
944 bool ok;
945 NTSTATUS status;
947 cur_offset = dptr_TellDir(dirptr);
948 prev_offset = cur_offset;
949 dname = dptr_ReadDirName(ctx, dirptr, &cur_offset, &sbuf);
951 DEBUG(6,("smbd_dirptr_get_entry: dirptr 0x%lx now at offset %ld\n",
952 (long)dirptr, cur_offset));
954 if (dname == NULL) {
955 return false;
958 isdots = (ISDOT(dname) || ISDOTDOT(dname));
959 if (dont_descend && !isdots) {
960 TALLOC_FREE(dname);
961 continue;
965 * fname may get mangled, dname is never mangled.
966 * Whenever we're accessing the filesystem we use
967 * pathreal which is composed from dname.
970 ok = match_fn(ctx, private_data, dname, mask, &fname);
971 if (!ok) {
972 TALLOC_FREE(dname);
973 continue;
976 pathreal = talloc_asprintf(ctx, "%s%s%s",
977 dirptr->path,
978 needslash?"/":"",
979 dname);
980 if (!pathreal) {
981 TALLOC_FREE(dname);
982 TALLOC_FREE(fname);
983 return false;
986 /* Create smb_fname with NULL stream_name. */
987 ZERO_STRUCT(smb_fname);
988 smb_fname.base_name = pathreal;
989 smb_fname.st = sbuf;
991 ok = mode_fn(ctx, private_data, &smb_fname, &mode);
992 if (!ok) {
993 TALLOC_FREE(dname);
994 TALLOC_FREE(fname);
995 TALLOC_FREE(pathreal);
996 continue;
999 if (!dir_check_ftype(conn, mode, dirtype)) {
1000 DEBUG(5,("[%s] attribs 0x%x didn't match 0x%x\n",
1001 fname, (unsigned int)mode, (unsigned int)dirtype));
1002 TALLOC_FREE(dname);
1003 TALLOC_FREE(fname);
1004 TALLOC_FREE(pathreal);
1005 continue;
1008 if (ask_sharemode) {
1009 struct timespec write_time_ts;
1010 struct file_id fileid;
1012 fileid = vfs_file_id_from_sbuf(conn,
1013 &smb_fname.st);
1014 get_file_infos(fileid, 0, NULL, &write_time_ts);
1015 if (!null_timespec(write_time_ts)) {
1016 update_stat_ex_mtime(&smb_fname.st,
1017 write_time_ts);
1021 DEBUG(3,("smbd_dirptr_get_entry mask=[%s] found %s "
1022 "fname=%s (%s)\n",
1023 mask, smb_fname_str_dbg(&smb_fname),
1024 dname, fname));
1026 DirCacheAdd(dirptr->dir_hnd, dname, cur_offset);
1028 TALLOC_FREE(dname);
1030 status = copy_smb_filename(ctx, &smb_fname, _smb_fname);
1031 TALLOC_FREE(pathreal);
1032 if (!NT_STATUS_IS_OK(status)) {
1033 return false;
1035 *_fname = fname;
1036 *_mode = mode;
1037 *_prev_offset = prev_offset;
1039 return true;
1042 return false;
1045 /****************************************************************************
1046 Get an 8.3 directory entry.
1047 ****************************************************************************/
1049 static bool smbd_dirptr_8_3_match_fn(TALLOC_CTX *ctx,
1050 void *private_data,
1051 const char *dname,
1052 const char *mask,
1053 char **_fname)
1055 connection_struct *conn = (connection_struct *)private_data;
1057 if ((strcmp(mask,"*.*") == 0) ||
1058 mask_match_search(dname, mask, false) ||
1059 mangle_mask_match(conn, dname, mask)) {
1060 char mname[13];
1061 const char *fname;
1063 if (!mangle_is_8_3(dname, false, conn->params)) {
1064 bool ok = name_to_8_3(dname, mname, false,
1065 conn->params);
1066 if (!ok) {
1067 return false;
1069 fname = mname;
1070 } else {
1071 fname = dname;
1074 *_fname = talloc_strdup(ctx, fname);
1075 if (*_fname == NULL) {
1076 return false;
1079 return true;
1082 return false;
1085 static bool smbd_dirptr_8_3_mode_fn(TALLOC_CTX *ctx,
1086 void *private_data,
1087 struct smb_filename *smb_fname,
1088 uint32_t *_mode)
1090 connection_struct *conn = (connection_struct *)private_data;
1092 if (!VALID_STAT(smb_fname->st)) {
1093 if ((SMB_VFS_STAT(conn, smb_fname)) != 0) {
1094 DEBUG(5,("smbd_dirptr_8_3_mode_fn: "
1095 "Couldn't stat [%s]. Error "
1096 "= %s\n",
1097 smb_fname_str_dbg(smb_fname),
1098 strerror(errno)));
1099 return false;
1103 *_mode = dos_mode(conn, smb_fname);
1104 return true;
1107 bool get_dir_entry(TALLOC_CTX *ctx,
1108 struct dptr_struct *dirptr,
1109 const char *mask,
1110 uint32_t dirtype,
1111 char **_fname,
1112 SMB_OFF_T *_size,
1113 uint32_t *_mode,
1114 struct timespec *_date,
1115 bool check_descend,
1116 bool ask_sharemode)
1118 connection_struct *conn = dirptr->conn;
1119 char *fname = NULL;
1120 struct smb_filename *smb_fname = NULL;
1121 uint32_t mode = 0;
1122 long prev_offset;
1123 bool ok;
1125 ok = smbd_dirptr_get_entry(ctx,
1126 dirptr,
1127 mask,
1128 dirtype,
1129 check_descend,
1130 ask_sharemode,
1131 smbd_dirptr_8_3_match_fn,
1132 smbd_dirptr_8_3_mode_fn,
1133 conn,
1134 &fname,
1135 &smb_fname,
1136 &mode,
1137 &prev_offset);
1138 if (!ok) {
1139 return false;
1142 *_fname = talloc_move(ctx, &fname);
1143 *_size = smb_fname->st.st_ex_size;
1144 *_mode = mode;
1145 *_date = smb_fname->st.st_ex_mtime;
1146 TALLOC_FREE(smb_fname);
1147 return true;
1150 /*******************************************************************
1151 Check to see if a user can read a file. This is only approximate,
1152 it is used as part of the "hide unreadable" option. Don't
1153 use it for anything security sensitive.
1154 ********************************************************************/
1156 static bool user_can_read_file(connection_struct *conn,
1157 struct smb_filename *smb_fname)
1160 * Never hide files from the root user.
1161 * We use (uid_t)0 here not sec_initial_uid()
1162 * as make test uses a single user context.
1165 if (get_current_uid(conn) == (uid_t)0) {
1166 return True;
1169 return can_access_file_acl(conn, smb_fname, FILE_READ_DATA);
1172 /*******************************************************************
1173 Check to see if a user can write a file (and only files, we do not
1174 check dirs on this one). This is only approximate,
1175 it is used as part of the "hide unwriteable" option. Don't
1176 use it for anything security sensitive.
1177 ********************************************************************/
1179 static bool user_can_write_file(connection_struct *conn,
1180 const struct smb_filename *smb_fname)
1183 * Never hide files from the root user.
1184 * We use (uid_t)0 here not sec_initial_uid()
1185 * as make test uses a single user context.
1188 if (get_current_uid(conn) == (uid_t)0) {
1189 return True;
1192 SMB_ASSERT(VALID_STAT(smb_fname->st));
1194 /* Pseudo-open the file */
1196 if(S_ISDIR(smb_fname->st.st_ex_mode)) {
1197 return True;
1200 return can_write_to_file(conn, smb_fname);
1203 /*******************************************************************
1204 Is a file a "special" type ?
1205 ********************************************************************/
1207 static bool file_is_special(connection_struct *conn,
1208 const struct smb_filename *smb_fname)
1211 * Never hide files from the root user.
1212 * We use (uid_t)0 here not sec_initial_uid()
1213 * as make test uses a single user context.
1216 if (get_current_uid(conn) == (uid_t)0) {
1217 return False;
1220 SMB_ASSERT(VALID_STAT(smb_fname->st));
1222 if (S_ISREG(smb_fname->st.st_ex_mode) ||
1223 S_ISDIR(smb_fname->st.st_ex_mode) ||
1224 S_ISLNK(smb_fname->st.st_ex_mode))
1225 return False;
1227 return True;
1230 /*******************************************************************
1231 Should the file be seen by the client?
1232 NOTE: A successful return is no guarantee of the file's existence.
1233 ********************************************************************/
1235 bool is_visible_file(connection_struct *conn, const char *dir_path,
1236 const char *name, SMB_STRUCT_STAT *pst, bool use_veto)
1238 bool hide_unreadable = lp_hideunreadable(SNUM(conn));
1239 bool hide_unwriteable = lp_hideunwriteable_files(SNUM(conn));
1240 bool hide_special = lp_hide_special_files(SNUM(conn));
1241 char *entry = NULL;
1242 struct smb_filename *smb_fname_base = NULL;
1243 NTSTATUS status;
1244 bool ret = false;
1246 if ((strcmp(".",name) == 0) || (strcmp("..",name) == 0)) {
1247 return True; /* . and .. are always visible. */
1250 /* If it's a vetoed file, pretend it doesn't even exist */
1251 if (use_veto && IS_VETO_PATH(conn, name)) {
1252 DEBUG(10,("is_visible_file: file %s is vetoed.\n", name ));
1253 return False;
1256 if (hide_unreadable || hide_unwriteable || hide_special) {
1257 entry = talloc_asprintf(talloc_tos(), "%s/%s", dir_path, name);
1258 if (!entry) {
1259 ret = false;
1260 goto out;
1263 /* Create an smb_filename with stream_name == NULL. */
1264 status = create_synthetic_smb_fname(talloc_tos(), entry, NULL,
1265 pst, &smb_fname_base);
1266 if (!NT_STATUS_IS_OK(status)) {
1267 ret = false;
1268 goto out;
1271 /* If the file name does not exist, there's no point checking
1272 * the configuration options. We succeed, on the basis that the
1273 * checks *might* have passed if the file was present.
1275 if (!VALID_STAT(*pst)) {
1276 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
1277 ret = true;
1278 goto out;
1279 } else {
1280 *pst = smb_fname_base->st;
1284 /* Honour _hide unreadable_ option */
1285 if (hide_unreadable &&
1286 !user_can_read_file(conn, smb_fname_base)) {
1287 DEBUG(10,("is_visible_file: file %s is unreadable.\n",
1288 entry ));
1289 ret = false;
1290 goto out;
1292 /* Honour _hide unwriteable_ option */
1293 if (hide_unwriteable && !user_can_write_file(conn,
1294 smb_fname_base)) {
1295 DEBUG(10,("is_visible_file: file %s is unwritable.\n",
1296 entry ));
1297 ret = false;
1298 goto out;
1300 /* Honour _hide_special_ option */
1301 if (hide_special && file_is_special(conn, smb_fname_base)) {
1302 DEBUG(10,("is_visible_file: file %s is special.\n",
1303 entry ));
1304 ret = false;
1305 goto out;
1309 ret = true;
1310 out:
1311 TALLOC_FREE(smb_fname_base);
1312 TALLOC_FREE(entry);
1313 return ret;
1316 static int smb_Dir_destructor(struct smb_Dir *dirp)
1318 if (dirp->dir) {
1319 #ifdef HAVE_DIRFD
1320 if (dirp->conn->sconn) {
1321 files_struct *fsp = file_find_fd(dirp->conn->sconn,
1322 dirfd(dirp->dir));
1323 if (fsp) {
1324 /* The call below closes the underlying fd. */
1325 fsp->fh->fd = -1;
1328 #endif
1329 SMB_VFS_CLOSEDIR(dirp->conn,dirp->dir);
1331 if (dirp->conn->sconn) {
1332 dirp->conn->sconn->searches.dirhandles_open--;
1334 return 0;
1337 /*******************************************************************
1338 Open a directory.
1339 ********************************************************************/
1341 struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn,
1342 const char *name,
1343 const char *mask,
1344 uint32 attr)
1346 struct smb_Dir *dirp = talloc_zero(mem_ctx, struct smb_Dir);
1347 struct smbd_server_connection *sconn = conn->sconn;
1349 if (!dirp) {
1350 return NULL;
1353 dirp->conn = conn;
1354 dirp->name_cache_size = lp_directory_name_cache_size(SNUM(conn));
1356 dirp->dir_path = talloc_strdup(dirp, name);
1357 if (!dirp->dir_path) {
1358 errno = ENOMEM;
1359 goto fail;
1362 if (sconn) {
1363 sconn->searches.dirhandles_open++;
1365 talloc_set_destructor(dirp, smb_Dir_destructor);
1367 dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path, mask, attr);
1368 if (!dirp->dir) {
1369 DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp->dir_path,
1370 strerror(errno) ));
1371 goto fail;
1374 return dirp;
1376 fail:
1377 TALLOC_FREE(dirp);
1378 return NULL;
1381 /*******************************************************************
1382 Open a directory from an fsp.
1383 ********************************************************************/
1385 static struct smb_Dir *OpenDir_fsp(TALLOC_CTX *mem_ctx, connection_struct *conn,
1386 files_struct *fsp,
1387 const char *mask,
1388 uint32 attr)
1390 struct smb_Dir *dirp = talloc_zero(mem_ctx, struct smb_Dir);
1391 struct smbd_server_connection *sconn = conn->sconn;
1393 if (!dirp) {
1394 return NULL;
1397 dirp->conn = conn;
1398 dirp->name_cache_size = lp_directory_name_cache_size(SNUM(conn));
1400 dirp->dir_path = talloc_strdup(dirp, fsp->fsp_name->base_name);
1401 if (!dirp->dir_path) {
1402 errno = ENOMEM;
1403 goto fail;
1406 if (sconn) {
1407 sconn->searches.dirhandles_open++;
1409 talloc_set_destructor(dirp, smb_Dir_destructor);
1411 if (fsp->is_directory && fsp->fh->fd != -1) {
1412 dirp->dir = SMB_VFS_FDOPENDIR(fsp, mask, attr);
1413 if (dirp->dir == NULL) {
1414 DEBUG(10,("OpenDir_fsp: SMB_VFS_FDOPENDIR on %s returned "
1415 "NULL (%s)\n",
1416 dirp->dir_path,
1417 strerror(errno)));
1418 if (errno != ENOSYS) {
1419 return NULL;
1424 if (dirp->dir == NULL) {
1425 /* FDOPENDIR didn't work. Use OPENDIR instead. */
1426 dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path, mask, attr);
1429 if (!dirp->dir) {
1430 DEBUG(5,("OpenDir_fsp: Can't open %s. %s\n", dirp->dir_path,
1431 strerror(errno) ));
1432 goto fail;
1435 return dirp;
1437 fail:
1438 TALLOC_FREE(dirp);
1439 return NULL;
1443 /*******************************************************************
1444 Read from a directory.
1445 Return directory entry, current offset, and optional stat information.
1446 Don't check for veto or invisible files.
1447 ********************************************************************/
1449 const char *ReadDirName(struct smb_Dir *dirp, long *poffset,
1450 SMB_STRUCT_STAT *sbuf, char **ptalloced)
1452 const char *n;
1453 char *talloced = NULL;
1454 connection_struct *conn = dirp->conn;
1456 /* Cheat to allow . and .. to be the first entries returned. */
1457 if (((*poffset == START_OF_DIRECTORY_OFFSET) ||
1458 (*poffset == DOT_DOT_DIRECTORY_OFFSET)) && (dirp->file_number < 2))
1460 if (dirp->file_number == 0) {
1461 n = ".";
1462 *poffset = dirp->offset = START_OF_DIRECTORY_OFFSET;
1463 } else {
1464 n = "..";
1465 *poffset = dirp->offset = DOT_DOT_DIRECTORY_OFFSET;
1467 dirp->file_number++;
1468 *ptalloced = NULL;
1469 return n;
1470 } else if (*poffset == END_OF_DIRECTORY_OFFSET) {
1471 *poffset = dirp->offset = END_OF_DIRECTORY_OFFSET;
1472 return NULL;
1473 } else {
1474 /* A real offset, seek to it. */
1475 SeekDir(dirp, *poffset);
1478 while ((n = vfs_readdirname(conn, dirp->dir, sbuf, &talloced))) {
1479 /* Ignore . and .. - we've already returned them. */
1480 if (*n == '.') {
1481 if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
1482 TALLOC_FREE(talloced);
1483 continue;
1486 *poffset = dirp->offset = SMB_VFS_TELLDIR(conn, dirp->dir);
1487 *ptalloced = talloced;
1488 dirp->file_number++;
1489 return n;
1491 *poffset = dirp->offset = END_OF_DIRECTORY_OFFSET;
1492 *ptalloced = NULL;
1493 return NULL;
1496 /*******************************************************************
1497 Rewind to the start.
1498 ********************************************************************/
1500 void RewindDir(struct smb_Dir *dirp, long *poffset)
1502 SMB_VFS_REWINDDIR(dirp->conn, dirp->dir);
1503 dirp->file_number = 0;
1504 dirp->offset = START_OF_DIRECTORY_OFFSET;
1505 *poffset = START_OF_DIRECTORY_OFFSET;
1508 /*******************************************************************
1509 Seek a dir.
1510 ********************************************************************/
1512 void SeekDir(struct smb_Dir *dirp, long offset)
1514 if (offset != dirp->offset) {
1515 if (offset == START_OF_DIRECTORY_OFFSET) {
1516 RewindDir(dirp, &offset);
1518 * Ok we should really set the file number here
1519 * to 1 to enable ".." to be returned next. Trouble
1520 * is I'm worried about callers using SeekDir(dirp,0)
1521 * as equivalent to RewindDir(). So leave this alone
1522 * for now.
1524 } else if (offset == DOT_DOT_DIRECTORY_OFFSET) {
1525 RewindDir(dirp, &offset);
1527 * Set the file number to 2 - we want to get the first
1528 * real file entry (the one we return after "..")
1529 * on the next ReadDir.
1531 dirp->file_number = 2;
1532 } else if (offset == END_OF_DIRECTORY_OFFSET) {
1533 ; /* Don't seek in this case. */
1534 } else {
1535 SMB_VFS_SEEKDIR(dirp->conn, dirp->dir, offset);
1537 dirp->offset = offset;
1541 /*******************************************************************
1542 Tell a dir position.
1543 ********************************************************************/
1545 long TellDir(struct smb_Dir *dirp)
1547 return(dirp->offset);
1550 /*******************************************************************
1551 Add an entry into the dcache.
1552 ********************************************************************/
1554 void DirCacheAdd(struct smb_Dir *dirp, const char *name, long offset)
1556 struct name_cache_entry *e;
1558 if (dirp->name_cache_size == 0) {
1559 return;
1562 if (dirp->name_cache == NULL) {
1563 dirp->name_cache = talloc_zero_array(
1564 dirp, struct name_cache_entry, dirp->name_cache_size);
1566 if (dirp->name_cache == NULL) {
1567 return;
1571 dirp->name_cache_index = (dirp->name_cache_index+1) %
1572 dirp->name_cache_size;
1573 e = &dirp->name_cache[dirp->name_cache_index];
1574 TALLOC_FREE(e->name);
1575 e->name = talloc_strdup(dirp, name);
1576 e->offset = offset;
1579 /*******************************************************************
1580 Find an entry by name. Leave us at the offset after it.
1581 Don't check for veto or invisible files.
1582 ********************************************************************/
1584 bool SearchDir(struct smb_Dir *dirp, const char *name, long *poffset)
1586 int i;
1587 const char *entry = NULL;
1588 char *talloced = NULL;
1589 connection_struct *conn = dirp->conn;
1591 /* Search back in the name cache. */
1592 if (dirp->name_cache_size && dirp->name_cache) {
1593 for (i = dirp->name_cache_index; i >= 0; i--) {
1594 struct name_cache_entry *e = &dirp->name_cache[i];
1595 if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1596 *poffset = e->offset;
1597 SeekDir(dirp, e->offset);
1598 return True;
1601 for (i = dirp->name_cache_size - 1; i > dirp->name_cache_index; i--) {
1602 struct name_cache_entry *e = &dirp->name_cache[i];
1603 if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1604 *poffset = e->offset;
1605 SeekDir(dirp, e->offset);
1606 return True;
1611 /* Not found in the name cache. Rewind directory and start from scratch. */
1612 SMB_VFS_REWINDDIR(conn, dirp->dir);
1613 dirp->file_number = 0;
1614 *poffset = START_OF_DIRECTORY_OFFSET;
1615 while ((entry = ReadDirName(dirp, poffset, NULL, &talloced))) {
1616 if (conn->case_sensitive ? (strcmp(entry, name) == 0) : strequal(entry, name)) {
1617 TALLOC_FREE(talloced);
1618 return True;
1620 TALLOC_FREE(talloced);
1622 return False;
1625 /*****************************************************************
1626 Is this directory empty ?
1627 *****************************************************************/
1629 NTSTATUS smbd_can_delete_directory(struct connection_struct *conn,
1630 const char *dirname)
1632 NTSTATUS status = NT_STATUS_OK;
1633 long dirpos = 0;
1634 const char *dname = NULL;
1635 char *talloced = NULL;
1636 SMB_STRUCT_STAT st;
1637 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
1638 dirname, NULL, 0);
1640 if (!dir_hnd) {
1641 return map_nt_error_from_unix(errno);
1644 while ((dname = ReadDirName(dir_hnd, &dirpos, &st, &talloced))) {
1645 /* Quick check for "." and ".." */
1646 if (dname[0] == '.') {
1647 if (!dname[1] || (dname[1] == '.' && !dname[2])) {
1648 TALLOC_FREE(talloced);
1649 continue;
1653 if (!is_visible_file(conn, dirname, dname, &st, True)) {
1654 TALLOC_FREE(talloced);
1655 continue;
1658 DEBUG(10,("can_delete_directory: got name %s - can't delete\n",
1659 dname ));
1660 status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1661 break;
1663 TALLOC_FREE(talloced);
1664 TALLOC_FREE(dir_hnd);
1666 return status;