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/>.
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 {
44 connection_struct *conn;
48 size_t name_cache_size;
49 struct name_cache_entry *name_cache;
50 unsigned int name_cache_index;
51 unsigned int file_number;
55 struct dptr_struct *next, *prev;
58 struct connection_struct *conn;
59 struct smb_Dir *dir_hnd;
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,
73 #define INVALID_DPTR_KEY (-3)
75 /****************************************************************************
77 ****************************************************************************/
79 bool make_dir_struct(TALLOC_CTX *ctx,
89 char *mask2 = talloc_strdup(ctx, mask);
95 if ((mode & FILE_ATTRIBUTE_DIRECTORY) != 0) {
100 if ((p = strchr_m(mask2,'.')) != NULL) {
102 push_ascii(buf+1,mask2,8, 0);
103 push_ascii(buf+9,p+1,3, 0);
106 push_ascii(buf+1,mask2,11, 0);
109 memset(buf+21,'\0',DIR_STRUCT_SIZE-21);
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));
121 /****************************************************************************
122 Initialise the dir bitmap.
123 ****************************************************************************/
125 bool init_dptrs(struct smbd_server_connection *sconn)
127 if (sconn->searches.dptr_bmap) {
131 sconn->searches.dptr_bmap = bitmap_talloc(
132 sconn, MAX_DIRECTORY_HANDLES);
134 if (sconn->searches.dptr_bmap == NULL) {
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)
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);
167 DEBUG(0,("No dptrs available to idle ?\n"));
172 * Idle the oldest pointer.
175 for(; dptr; dptr = DLIST_PREV(dptr)) {
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,
206 DLIST_PROMOTE(sconn->searches.dirptrs,dptr);
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);
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);
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);
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));
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",
275 bitmap_clear(sconn->searches.dptr_bmap, dptr->dnum - 1);
278 TALLOC_FREE(dptr->dir_hnd);
280 /* Lanman 2 specific code */
281 SAFE_FREE(dptr->wcard);
282 SAFE_FREE(dptr->path);
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)
297 /* OS/2 seems to use -1 to indicate "close all directories" */
299 struct dptr_struct *next;
300 for(dptr = sconn->searches.dirptrs; dptr; dptr = next) {
302 dptr_close_internal(dptr);
304 *key = INVALID_DPTR_KEY;
308 dptr = dptr_get(sconn, *key, true);
311 DEBUG(0,("Invalid key %d given to dptr_close\n", *key));
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;
333 for(dptr = sconn->searches.dirptrs; dptr; 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;
354 for(dptr = sconn->searches.dirptrs; dptr; dptr = dptr->next) {
355 if (dptr->conn == conn && dptr->dir_hnd) {
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) {
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,
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)
394 DEBUG(0,("No old dptrs available to close oldest ?\n"));
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);
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;
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));
438 DEBUG(0,("dptr_create: called with fake connection_struct\n"));
439 return NT_STATUS_INTERNAL_ERROR;
443 return NT_STATUS_INVALID_PARAMETER;
447 dir_hnd = OpenDir_fsp(NULL, conn, fsp, wcard, attr);
449 status = check_name(conn,path);
450 if (!NT_STATUS_IS_OK(status)) {
453 dir_hnd = OpenDir(NULL, conn, path, wcard, attr);
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);
466 DEBUG(0,("malloc fail in dptr_create.\n"));
467 TALLOC_FREE(dir_hnd);
468 return NT_STATUS_NO_MEMORY;
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));
497 TALLOC_FREE(dir_hnd);
498 return NT_STATUS_TOO_MANY_OPENED_FILES;
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
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));
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 dptr->path = SMB_STRDUP(path);
539 bitmap_clear(sconn->searches.dptr_bmap, dptr->dnum - 1);
541 TALLOC_FREE(dir_hnd);
542 return NT_STATUS_NO_MEMORY;
545 dptr->dir_hnd = dir_hnd;
547 dptr->expect_close = expect_close;
548 dptr->wcard = SMB_STRDUP(wcard);
550 bitmap_clear(sconn->searches.dptr_bmap, dptr->dnum - 1);
551 SAFE_FREE(dptr->path);
553 TALLOC_FREE(dir_hnd);
554 return NT_STATUS_NO_MEMORY;
556 if (lp_posix_pathnames() || (wcard[0] == '.' && wcard[1] == 0)) {
557 dptr->has_wild = True;
559 dptr->has_wild = wcard_has_wild;
564 DLIST_ADD(sconn->searches.dirptrs, dptr);
566 DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n",
567 dptr->dnum,path,expect_close));
575 /****************************************************************************
576 Wrapper functions to access the lower level directory handles.
577 ****************************************************************************/
579 void dptr_CloseDir(files_struct *fsp)
583 * Ugly hack. We have defined fdopendir to return ENOSYS if dirfd also isn't
584 * present. I hate Solaris. JRA.
587 if (fsp->fh->fd != -1 &&
588 fsp->dptr->dir_hnd &&
589 dirfd(fsp->dptr->dir_hnd->dir)) {
590 /* The call below closes the underlying fd. */
594 dptr_close_internal(fsp->dptr);
599 void dptr_SeekDir(struct dptr_struct *dptr, long offset)
601 SeekDir(dptr->dir_hnd, offset);
604 long dptr_TellDir(struct dptr_struct *dptr)
606 return TellDir(dptr->dir_hnd);
609 bool dptr_has_wild(struct dptr_struct *dptr)
611 return dptr->has_wild;
614 int dptr_dnum(struct dptr_struct *dptr)
619 /****************************************************************************
620 Return the next visible file name, skipping veto'd and invisible files.
621 ****************************************************************************/
623 static const char *dptr_normal_ReadDirName(struct dptr_struct *dptr,
624 long *poffset, SMB_STRUCT_STAT *pst,
627 /* Normal search for the next file. */
629 char *talloced = NULL;
631 while ((name = ReadDirName(dptr->dir_hnd, poffset, pst, &talloced))
633 if (is_visible_file(dptr->conn, dptr->path, name, pst, True)) {
634 *ptalloced = talloced;
637 TALLOC_FREE(talloced);
642 /****************************************************************************
643 Return the next visible file name, skipping veto'd and invisible files.
644 ****************************************************************************/
646 char *dptr_ReadDirName(TALLOC_CTX *ctx,
647 struct dptr_struct *dptr,
649 SMB_STRUCT_STAT *pst)
651 struct smb_filename smb_fname_base;
653 const char *name_temp = NULL;
654 char *talloced = NULL;
655 char *pathreal = NULL;
656 char *found_name = NULL;
659 SET_STAT_INVALID(*pst);
661 if (dptr->has_wild || dptr->did_stat) {
662 name_temp = dptr_normal_ReadDirName(dptr, poffset, pst,
664 if (name_temp == NULL) {
667 if (talloced != NULL) {
668 return talloc_move(ctx, &talloced);
670 return talloc_strdup(ctx, name_temp);
673 /* If poffset is -1 then we know we returned this name before and we
674 * have no wildcards. We're at the end of the directory. */
675 if (*poffset == END_OF_DIRECTORY_OFFSET) {
679 /* We know the stored wcard contains no wildcard characters.
680 * See if we can match with a stat call. If we can't, then set
681 * did_stat to true to ensure we only do this once and keep
684 dptr->did_stat = true;
686 /* First check if it should be visible. */
687 if (!is_visible_file(dptr->conn, dptr->path, dptr->wcard,
690 /* This only returns false if the file was found, but
691 is explicitly not visible. Set us to end of
692 directory, but return NULL as we know we can't ever
697 if (VALID_STAT(*pst)) {
698 name = talloc_strdup(ctx, dptr->wcard);
702 pathreal = talloc_asprintf(ctx,
709 /* Create an smb_filename with stream_name == NULL. */
710 ZERO_STRUCT(smb_fname_base);
711 smb_fname_base.base_name = pathreal;
713 if (SMB_VFS_STAT(dptr->conn, &smb_fname_base) == 0) {
714 *pst = smb_fname_base.st;
715 name = talloc_strdup(ctx, dptr->wcard);
718 /* If we get any other error than ENOENT or ENOTDIR
719 then the file exists we just can't stat it. */
720 if (errno != ENOENT && errno != ENOTDIR) {
721 name = talloc_strdup(ctx, dptr->wcard);
726 /* Stat failed. We know this is authoratiative if we are
727 * providing case sensitive semantics or the underlying
728 * filesystem is case sensitive.
730 if (dptr->conn->case_sensitive ||
731 !(dptr->conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH))
737 * Try case-insensitive stat if the fs has the ability. This avoids
738 * scanning the whole directory.
740 ret = SMB_VFS_GET_REAL_FILENAME(dptr->conn, dptr->path, dptr->wcard,
745 } else if (errno == ENOENT) {
746 /* The case-insensitive lookup was authoritative. */
750 TALLOC_FREE(pathreal);
752 name_temp = dptr_normal_ReadDirName(dptr, poffset, pst, &talloced);
753 if (name_temp == NULL) {
756 if (talloced != NULL) {
757 return talloc_move(ctx, &talloced);
759 return talloc_strdup(ctx, name_temp);
762 TALLOC_FREE(pathreal);
764 /* We need to set the underlying dir_hnd offset to -1
765 * also as this function is usually called with the
766 * output from TellDir. */
767 dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
771 /****************************************************************************
772 Search for a file by name, skipping veto'ed and not visible files.
773 ****************************************************************************/
775 bool dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, SMB_STRUCT_STAT *pst)
777 SET_STAT_INVALID(*pst);
779 if (!dptr->has_wild && (dptr->dir_hnd->offset == END_OF_DIRECTORY_OFFSET)) {
780 /* This is a singleton directory and we're already at the end. */
781 *poffset = END_OF_DIRECTORY_OFFSET;
785 return SearchDir(dptr->dir_hnd, name, poffset);
788 /****************************************************************************
789 Add the name we're returning into the underlying cache.
790 ****************************************************************************/
792 void dptr_DirCacheAdd(struct dptr_struct *dptr, const char *name, long offset)
794 DirCacheAdd(dptr->dir_hnd, name, offset);
797 /****************************************************************************
798 Initialize variables & state data at the beginning of all search SMB requests.
799 ****************************************************************************/
800 void dptr_init_search_op(struct dptr_struct *dptr)
802 SMB_VFS_INIT_SEARCH_OP(dptr->conn, dptr->dir_hnd->dir);
805 /****************************************************************************
806 Fill the 5 byte server reserved dptr field.
807 ****************************************************************************/
809 bool dptr_fill(struct smbd_server_connection *sconn,
810 char *buf1,unsigned int key)
812 unsigned char *buf = (unsigned char *)buf1;
813 struct dptr_struct *dptr = dptr_get(sconn, key, false);
816 DEBUG(1,("filling null dirptr %d\n",key));
819 offset = (uint32)TellDir(dptr->dir_hnd);
820 DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key,
821 (long)dptr->dir_hnd,(int)offset));
827 /****************************************************************************
828 Fetch the dir ptr and seek it given the 5 byte server field.
829 ****************************************************************************/
831 struct dptr_struct *dptr_fetch(struct smbd_server_connection *sconn,
834 unsigned int key = *(unsigned char *)buf;
835 struct dptr_struct *dptr = dptr_get(sconn, key, false);
840 DEBUG(3,("fetched null dirptr %d\n",key));
844 offset = IVAL(buf,1);
845 if (offset == (uint32)-1) {
846 seekoff = END_OF_DIRECTORY_OFFSET;
848 seekoff = (long)offset;
850 SeekDir(dptr->dir_hnd,seekoff);
851 DEBUG(3,("fetching dirptr %d for path %s at offset %d\n",
852 key, dptr->path, (int)seekoff));
856 /****************************************************************************
858 ****************************************************************************/
860 struct dptr_struct *dptr_fetch_lanman2(struct smbd_server_connection *sconn,
863 struct dptr_struct *dptr = dptr_get(sconn, dptr_num, false);
866 DEBUG(3,("fetched null dirptr %d\n",dptr_num));
869 DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr->path));
873 /****************************************************************************
874 Check that a file matches a particular file type.
875 ****************************************************************************/
877 bool dir_check_ftype(connection_struct *conn, uint32 mode, uint32 dirtype)
881 /* Check the "may have" search bits. */
882 if (((mode & ~dirtype) & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DIRECTORY)) != 0)
885 /* Check the "must have" bits, which are the may have bits shifted eight */
886 /* If must have bit is set, the file/dir can not be returned in search unless the matching
887 file attribute is set */
888 mask = ((dirtype >> 8) & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)); /* & 0x37 */
890 if((mask & (mode & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM))) == mask) /* check if matching attribute present */
899 static bool mangle_mask_match(connection_struct *conn,
900 const char *filename,
905 if (!name_to_8_3(filename,mname,False,conn->params)) {
908 return mask_match_search(mname,mask,False);
911 bool smbd_dirptr_get_entry(TALLOC_CTX *ctx,
912 struct dptr_struct *dirptr,
917 bool (*match_fn)(TALLOC_CTX *ctx,
922 bool (*mode_fn)(TALLOC_CTX *ctx,
924 struct smb_filename *smb_fname,
928 struct smb_filename **_smb_fname,
932 connection_struct *conn = dirptr->conn;
938 needslash = ( dirptr->path[strlen(dirptr->path) -1] != '/');
943 SMB_STRUCT_STAT sbuf;
947 char *pathreal = NULL;
948 struct smb_filename smb_fname;
953 cur_offset = dptr_TellDir(dirptr);
954 prev_offset = cur_offset;
955 dname = dptr_ReadDirName(ctx, dirptr, &cur_offset, &sbuf);
957 DEBUG(6,("smbd_dirptr_get_entry: dirptr 0x%lx now at offset %ld\n",
958 (long)dirptr, cur_offset));
964 isdots = (ISDOT(dname) || ISDOTDOT(dname));
965 if (dont_descend && !isdots) {
971 * fname may get mangled, dname is never mangled.
972 * Whenever we're accessing the filesystem we use
973 * pathreal which is composed from dname.
976 ok = match_fn(ctx, private_data, dname, mask, &fname);
982 pathreal = talloc_asprintf(ctx, "%s%s%s",
992 /* Create smb_fname with NULL stream_name. */
993 ZERO_STRUCT(smb_fname);
994 smb_fname.base_name = pathreal;
997 ok = mode_fn(ctx, private_data, &smb_fname, &mode);
1001 TALLOC_FREE(pathreal);
1005 if (!dir_check_ftype(conn, mode, dirtype)) {
1006 DEBUG(5,("[%s] attribs 0x%x didn't match 0x%x\n",
1007 fname, (unsigned int)mode, (unsigned int)dirtype));
1010 TALLOC_FREE(pathreal);
1014 if (ask_sharemode) {
1015 struct timespec write_time_ts;
1016 struct file_id fileid;
1018 fileid = vfs_file_id_from_sbuf(conn,
1020 get_file_infos(fileid, 0, NULL, &write_time_ts);
1021 if (!null_timespec(write_time_ts)) {
1022 update_stat_ex_mtime(&smb_fname.st,
1027 DEBUG(3,("smbd_dirptr_get_entry mask=[%s] found %s "
1029 mask, smb_fname_str_dbg(&smb_fname),
1032 DirCacheAdd(dirptr->dir_hnd, dname, cur_offset);
1036 status = copy_smb_filename(ctx, &smb_fname, _smb_fname);
1037 TALLOC_FREE(pathreal);
1038 if (!NT_STATUS_IS_OK(status)) {
1043 *_prev_offset = prev_offset;
1051 /****************************************************************************
1052 Get an 8.3 directory entry.
1053 ****************************************************************************/
1055 static bool smbd_dirptr_8_3_match_fn(TALLOC_CTX *ctx,
1061 connection_struct *conn = (connection_struct *)private_data;
1063 if ((strcmp(mask,"*.*") == 0) ||
1064 mask_match_search(dname, mask, false) ||
1065 mangle_mask_match(conn, dname, mask)) {
1069 if (!mangle_is_8_3(dname, false, conn->params)) {
1070 bool ok = name_to_8_3(dname, mname, false,
1080 *_fname = talloc_strdup(ctx, fname);
1081 if (*_fname == NULL) {
1091 static bool smbd_dirptr_8_3_mode_fn(TALLOC_CTX *ctx,
1093 struct smb_filename *smb_fname,
1096 connection_struct *conn = (connection_struct *)private_data;
1098 if (!VALID_STAT(smb_fname->st)) {
1099 if ((SMB_VFS_STAT(conn, smb_fname)) != 0) {
1100 DEBUG(5,("smbd_dirptr_8_3_mode_fn: "
1101 "Couldn't stat [%s]. Error "
1103 smb_fname_str_dbg(smb_fname),
1109 *_mode = dos_mode(conn, smb_fname);
1113 bool get_dir_entry(TALLOC_CTX *ctx,
1114 struct dptr_struct *dirptr,
1120 struct timespec *_date,
1124 connection_struct *conn = dirptr->conn;
1126 struct smb_filename *smb_fname = NULL;
1131 ok = smbd_dirptr_get_entry(ctx,
1137 smbd_dirptr_8_3_match_fn,
1138 smbd_dirptr_8_3_mode_fn,
1148 *_fname = talloc_move(ctx, &fname);
1149 *_size = smb_fname->st.st_ex_size;
1151 *_date = smb_fname->st.st_ex_mtime;
1152 TALLOC_FREE(smb_fname);
1156 /*******************************************************************
1157 Check to see if a user can read a file. This is only approximate,
1158 it is used as part of the "hide unreadable" option. Don't
1159 use it for anything security sensitive.
1160 ********************************************************************/
1162 static bool user_can_read_file(connection_struct *conn,
1163 struct smb_filename *smb_fname)
1166 * Never hide files from the root user.
1167 * We use (uid_t)0 here not sec_initial_uid()
1168 * as make test uses a single user context.
1171 if (get_current_uid(conn) == (uid_t)0) {
1175 return can_access_file_acl(conn, smb_fname, FILE_READ_DATA);
1178 /*******************************************************************
1179 Check to see if a user can write a file (and only files, we do not
1180 check dirs on this one). This is only approximate,
1181 it is used as part of the "hide unwriteable" option. Don't
1182 use it for anything security sensitive.
1183 ********************************************************************/
1185 static bool user_can_write_file(connection_struct *conn,
1186 const struct smb_filename *smb_fname)
1189 * Never hide files from the root user.
1190 * We use (uid_t)0 here not sec_initial_uid()
1191 * as make test uses a single user context.
1194 if (get_current_uid(conn) == (uid_t)0) {
1198 SMB_ASSERT(VALID_STAT(smb_fname->st));
1200 /* Pseudo-open the file */
1202 if(S_ISDIR(smb_fname->st.st_ex_mode)) {
1206 return can_write_to_file(conn, smb_fname);
1209 /*******************************************************************
1210 Is a file a "special" type ?
1211 ********************************************************************/
1213 static bool file_is_special(connection_struct *conn,
1214 const struct smb_filename *smb_fname)
1217 * Never hide files from the root user.
1218 * We use (uid_t)0 here not sec_initial_uid()
1219 * as make test uses a single user context.
1222 if (get_current_uid(conn) == (uid_t)0) {
1226 SMB_ASSERT(VALID_STAT(smb_fname->st));
1228 if (S_ISREG(smb_fname->st.st_ex_mode) ||
1229 S_ISDIR(smb_fname->st.st_ex_mode) ||
1230 S_ISLNK(smb_fname->st.st_ex_mode))
1236 /*******************************************************************
1237 Should the file be seen by the client?
1238 NOTE: A successful return is no guarantee of the file's existence.
1239 ********************************************************************/
1241 bool is_visible_file(connection_struct *conn, const char *dir_path,
1242 const char *name, SMB_STRUCT_STAT *pst, bool use_veto)
1244 bool hide_unreadable = lp_hideunreadable(SNUM(conn));
1245 bool hide_unwriteable = lp_hideunwriteable_files(SNUM(conn));
1246 bool hide_special = lp_hide_special_files(SNUM(conn));
1248 struct smb_filename *smb_fname_base = NULL;
1252 if ((strcmp(".",name) == 0) || (strcmp("..",name) == 0)) {
1253 return True; /* . and .. are always visible. */
1256 /* If it's a vetoed file, pretend it doesn't even exist */
1257 if (use_veto && IS_VETO_PATH(conn, name)) {
1258 DEBUG(10,("is_visible_file: file %s is vetoed.\n", name ));
1262 if (hide_unreadable || hide_unwriteable || hide_special) {
1263 entry = talloc_asprintf(talloc_tos(), "%s/%s", dir_path, name);
1269 /* Create an smb_filename with stream_name == NULL. */
1270 status = create_synthetic_smb_fname(talloc_tos(), entry, NULL,
1271 pst, &smb_fname_base);
1272 if (!NT_STATUS_IS_OK(status)) {
1277 /* If the file name does not exist, there's no point checking
1278 * the configuration options. We succeed, on the basis that the
1279 * checks *might* have passed if the file was present.
1281 if (!VALID_STAT(*pst)) {
1282 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
1286 *pst = smb_fname_base->st;
1290 /* Honour _hide unreadable_ option */
1291 if (hide_unreadable &&
1292 !user_can_read_file(conn, smb_fname_base)) {
1293 DEBUG(10,("is_visible_file: file %s is unreadable.\n",
1298 /* Honour _hide unwriteable_ option */
1299 if (hide_unwriteable && !user_can_write_file(conn,
1301 DEBUG(10,("is_visible_file: file %s is unwritable.\n",
1306 /* Honour _hide_special_ option */
1307 if (hide_special && file_is_special(conn, smb_fname_base)) {
1308 DEBUG(10,("is_visible_file: file %s is special.\n",
1317 TALLOC_FREE(smb_fname_base);
1322 static int smb_Dir_destructor(struct smb_Dir *dirp)
1326 if (dirp->conn->sconn) {
1327 files_struct *fsp = file_find_fd(dirp->conn->sconn,
1330 /* The call below closes the underlying fd. */
1335 SMB_VFS_CLOSEDIR(dirp->conn,dirp->dir);
1337 if (dirp->conn->sconn) {
1338 dirp->conn->sconn->searches.dirhandles_open--;
1343 /*******************************************************************
1345 ********************************************************************/
1347 struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn,
1352 struct smb_Dir *dirp = TALLOC_ZERO_P(mem_ctx, struct smb_Dir);
1353 struct smbd_server_connection *sconn = conn->sconn;
1360 dirp->name_cache_size = lp_directory_name_cache_size(SNUM(conn));
1362 dirp->dir_path = talloc_strdup(dirp, name);
1363 if (!dirp->dir_path) {
1369 sconn->searches.dirhandles_open++;
1371 talloc_set_destructor(dirp, smb_Dir_destructor);
1373 dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path, mask, attr);
1375 DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp->dir_path,
1387 /*******************************************************************
1388 Open a directory from an fsp.
1389 ********************************************************************/
1391 static struct smb_Dir *OpenDir_fsp(TALLOC_CTX *mem_ctx, connection_struct *conn,
1396 struct smb_Dir *dirp = TALLOC_ZERO_P(mem_ctx, struct smb_Dir);
1397 struct smbd_server_connection *sconn = conn->sconn;
1404 dirp->name_cache_size = lp_directory_name_cache_size(SNUM(conn));
1406 dirp->dir_path = talloc_strdup(dirp, fsp->fsp_name->base_name);
1407 if (!dirp->dir_path) {
1413 sconn->searches.dirhandles_open++;
1415 talloc_set_destructor(dirp, smb_Dir_destructor);
1417 if (fsp->is_directory && fsp->fh->fd != -1) {
1418 dirp->dir = SMB_VFS_FDOPENDIR(fsp, mask, attr);
1419 if (dirp->dir == NULL) {
1420 DEBUG(10,("OpenDir_fsp: SMB_VFS_FDOPENDIR on %s returned "
1424 if (errno != ENOSYS) {
1430 if (dirp->dir == NULL) {
1431 /* FDOPENDIR didn't work. Use OPENDIR instead. */
1432 dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path, mask, attr);
1436 DEBUG(5,("OpenDir_fsp: Can't open %s. %s\n", dirp->dir_path,
1449 /*******************************************************************
1450 Read from a directory.
1451 Return directory entry, current offset, and optional stat information.
1452 Don't check for veto or invisible files.
1453 ********************************************************************/
1455 const char *ReadDirName(struct smb_Dir *dirp, long *poffset,
1456 SMB_STRUCT_STAT *sbuf, char **ptalloced)
1459 char *talloced = NULL;
1460 connection_struct *conn = dirp->conn;
1462 /* Cheat to allow . and .. to be the first entries returned. */
1463 if (((*poffset == START_OF_DIRECTORY_OFFSET) ||
1464 (*poffset == DOT_DOT_DIRECTORY_OFFSET)) && (dirp->file_number < 2))
1466 if (dirp->file_number == 0) {
1468 *poffset = dirp->offset = START_OF_DIRECTORY_OFFSET;
1471 *poffset = dirp->offset = DOT_DOT_DIRECTORY_OFFSET;
1473 dirp->file_number++;
1476 } else if (*poffset == END_OF_DIRECTORY_OFFSET) {
1477 *poffset = dirp->offset = END_OF_DIRECTORY_OFFSET;
1480 /* A real offset, seek to it. */
1481 SeekDir(dirp, *poffset);
1484 while ((n = vfs_readdirname(conn, dirp->dir, sbuf, &talloced))) {
1485 /* Ignore . and .. - we've already returned them. */
1487 if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
1488 TALLOC_FREE(talloced);
1492 *poffset = dirp->offset = SMB_VFS_TELLDIR(conn, dirp->dir);
1493 *ptalloced = talloced;
1494 dirp->file_number++;
1497 *poffset = dirp->offset = END_OF_DIRECTORY_OFFSET;
1502 /*******************************************************************
1503 Rewind to the start.
1504 ********************************************************************/
1506 void RewindDir(struct smb_Dir *dirp, long *poffset)
1508 SMB_VFS_REWINDDIR(dirp->conn, dirp->dir);
1509 dirp->file_number = 0;
1510 dirp->offset = START_OF_DIRECTORY_OFFSET;
1511 *poffset = START_OF_DIRECTORY_OFFSET;
1514 /*******************************************************************
1516 ********************************************************************/
1518 void SeekDir(struct smb_Dir *dirp, long offset)
1520 if (offset != dirp->offset) {
1521 if (offset == START_OF_DIRECTORY_OFFSET) {
1522 RewindDir(dirp, &offset);
1524 * Ok we should really set the file number here
1525 * to 1 to enable ".." to be returned next. Trouble
1526 * is I'm worried about callers using SeekDir(dirp,0)
1527 * as equivalent to RewindDir(). So leave this alone
1530 } else if (offset == DOT_DOT_DIRECTORY_OFFSET) {
1531 RewindDir(dirp, &offset);
1533 * Set the file number to 2 - we want to get the first
1534 * real file entry (the one we return after "..")
1535 * on the next ReadDir.
1537 dirp->file_number = 2;
1538 } else if (offset == END_OF_DIRECTORY_OFFSET) {
1539 ; /* Don't seek in this case. */
1541 SMB_VFS_SEEKDIR(dirp->conn, dirp->dir, offset);
1543 dirp->offset = offset;
1547 /*******************************************************************
1548 Tell a dir position.
1549 ********************************************************************/
1551 long TellDir(struct smb_Dir *dirp)
1553 return(dirp->offset);
1556 /*******************************************************************
1557 Add an entry into the dcache.
1558 ********************************************************************/
1560 void DirCacheAdd(struct smb_Dir *dirp, const char *name, long offset)
1562 struct name_cache_entry *e;
1564 if (dirp->name_cache_size == 0) {
1568 if (dirp->name_cache == NULL) {
1569 dirp->name_cache = TALLOC_ZERO_ARRAY(
1570 dirp, struct name_cache_entry, dirp->name_cache_size);
1572 if (dirp->name_cache == NULL) {
1577 dirp->name_cache_index = (dirp->name_cache_index+1) %
1578 dirp->name_cache_size;
1579 e = &dirp->name_cache[dirp->name_cache_index];
1580 TALLOC_FREE(e->name);
1581 e->name = talloc_strdup(dirp, name);
1585 /*******************************************************************
1586 Find an entry by name. Leave us at the offset after it.
1587 Don't check for veto or invisible files.
1588 ********************************************************************/
1590 bool SearchDir(struct smb_Dir *dirp, const char *name, long *poffset)
1593 const char *entry = NULL;
1594 char *talloced = NULL;
1595 connection_struct *conn = dirp->conn;
1597 /* Search back in the name cache. */
1598 if (dirp->name_cache_size && dirp->name_cache) {
1599 for (i = dirp->name_cache_index; i >= 0; i--) {
1600 struct name_cache_entry *e = &dirp->name_cache[i];
1601 if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1602 *poffset = e->offset;
1603 SeekDir(dirp, e->offset);
1607 for (i = dirp->name_cache_size - 1; i > dirp->name_cache_index; i--) {
1608 struct name_cache_entry *e = &dirp->name_cache[i];
1609 if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
1610 *poffset = e->offset;
1611 SeekDir(dirp, e->offset);
1617 /* Not found in the name cache. Rewind directory and start from scratch. */
1618 SMB_VFS_REWINDDIR(conn, dirp->dir);
1619 dirp->file_number = 0;
1620 *poffset = START_OF_DIRECTORY_OFFSET;
1621 while ((entry = ReadDirName(dirp, poffset, NULL, &talloced))) {
1622 if (conn->case_sensitive ? (strcmp(entry, name) == 0) : strequal(entry, name)) {
1623 TALLOC_FREE(talloced);
1626 TALLOC_FREE(talloced);
1631 /*****************************************************************
1632 Is this directory empty ?
1633 *****************************************************************/
1635 NTSTATUS can_delete_directory(struct connection_struct *conn,
1636 const char *dirname)
1638 NTSTATUS status = NT_STATUS_OK;
1640 const char *dname = NULL;
1641 char *talloced = NULL;
1643 struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
1647 return map_nt_error_from_unix(errno);
1650 while ((dname = ReadDirName(dir_hnd, &dirpos, &st, &talloced))) {
1651 /* Quick check for "." and ".." */
1652 if (dname[0] == '.') {
1653 if (!dname[1] || (dname[1] == '.' && !dname[2])) {
1654 TALLOC_FREE(talloced);
1659 if (!is_visible_file(conn, dirname, dname, &st, True)) {
1660 TALLOC_FREE(talloced);
1664 DEBUG(10,("can_delete_directory: got name %s - can't delete\n",
1666 status = NT_STATUS_DIRECTORY_NOT_EMPTY;
1669 TALLOC_FREE(talloced);
1670 TALLOC_FREE(dir_hnd);