summaryrefslogtreecommitdiff
path: root/source3/smbd/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/smbd/dir.c')
-rw-r--r--source3/smbd/dir.c382
1 files changed, 162 insertions, 220 deletions
diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c
index 4d41f88f35..7f1237cb29 100644
--- a/source3/smbd/dir.c
+++ b/source3/smbd/dir.c
@@ -24,21 +24,43 @@
This module implements directory related functions for Samba.
*/
-typedef struct _dptr_struct {
- struct _dptr_struct *next, *prev;
+/* Make directory handle internals available. */
+
+#define NAME_CACHE_SIZE 100
+
+struct name_cache_entry {
+ char *name;
+ long offset;
+};
+
+struct smb_Dir {
+ connection_struct *conn;
+ DIR *dir;
+ long offset;
+ char *dir_path;
+ struct name_cache_entry *name_cache;
+ unsigned int name_cache_index;
+ BOOL hide_unreadable;
+ BOOL hide_unwriteable;
+ BOOL hide_special;
+ BOOL use_veto;
+};
+
+struct dptr_struct {
+ struct dptr_struct *next, *prev;
int dnum;
uint16 spid;
- connection_struct *conn;
- void *ptr;
+ struct connection_struct *conn;
+ struct smb_Dir *dir_hnd;
BOOL expect_close;
- char *wcard; /* Field only used for trans2_ searches */
- uint16 attr; /* Field only used for trans2_ searches */
+ char *wcard;
+ uint16 attr;
char *path;
-} dptr_struct;
+ BOOL has_wild; /* Set to true if the wcard entry has MS wildcard characters in it. */
+};
static struct bitmap *dptr_bmap;
-static dptr_struct *dirptrs;
-
+static struct dptr_struct *dirptrs;
static int dptrs_open = 0;
#define INVALID_DPTR_KEY (-3)
@@ -66,13 +88,12 @@ void init_dptrs(void)
Idle a dptr - the directory is closed but the control info is kept.
****************************************************************************/
-static void dptr_idle(dptr_struct *dptr)
+static void dptr_idle(struct dptr_struct *dptr)
{
- if (dptr->ptr) {
+ if (dptr->dir_hnd) {
DEBUG(4,("Idling dptr dnum %d\n",dptr->dnum));
- dptrs_open--;
- CloseDir(dptr->ptr);
- dptr->ptr = NULL;
+ CloseDir(dptr->dir_hnd);
+ dptr->dir_hnd = NULL;
}
}
@@ -82,7 +103,7 @@ static void dptr_idle(dptr_struct *dptr)
static void dptr_idleoldest(void)
{
- dptr_struct *dptr;
+ struct dptr_struct *dptr;
/*
* Go to the end of the list.
@@ -100,7 +121,7 @@ static void dptr_idleoldest(void)
*/
for(; dptr; dptr = dptr->prev) {
- if (dptr->ptr) {
+ if (dptr->dir_hnd) {
dptr_idle(dptr);
return;
}
@@ -108,21 +129,24 @@ static void dptr_idleoldest(void)
}
/****************************************************************************
- Get the dptr_struct for a dir index.
+ Get the struct dptr_struct for a dir index.
****************************************************************************/
-static dptr_struct *dptr_get(int key, BOOL forclose)
+static struct dptr_struct *dptr_get(int key, BOOL forclose)
{
- dptr_struct *dptr;
+ struct dptr_struct *dptr;
for(dptr = dirptrs; dptr; dptr = dptr->next) {
if(dptr->dnum == key) {
- if (!forclose && !dptr->ptr) {
+ if (!forclose && !dptr->dir_hnd) {
if (dptrs_open >= MAX_OPEN_DIRECTORIES)
dptr_idleoldest();
- DEBUG(4,("Reopening dptr key %d\n",key));
- if ((dptr->ptr = OpenDir(dptr->conn, dptr->path, True)))
- dptrs_open++;
+ DEBUG(4,("dptr_get: Reopening dptr key %d\n",key));
+ if (!(dptr->dir_hnd = OpenDir(dptr->conn, dptr->path, True))) {
+ DEBUG(4,("dptr_get: Failed to open %s (%s)\n",dptr->path,
+ strerror(errno)));
+ return False;
+ }
}
DLIST_PROMOTE(dirptrs,dptr);
return dptr;
@@ -132,94 +156,64 @@ static dptr_struct *dptr_get(int key, BOOL forclose)
}
/****************************************************************************
- Get the dptr ptr for a dir index.
-****************************************************************************/
-
-static void *dptr_ptr(int key)
-{
- dptr_struct *dptr = dptr_get(key, False);
-
- if (dptr)
- return(dptr->ptr);
- return(NULL);
-}
-
-/****************************************************************************
Get the dir path for a dir index.
****************************************************************************/
char *dptr_path(int key)
{
- dptr_struct *dptr = dptr_get(key, False);
-
+ struct dptr_struct *dptr = dptr_get(key, False);
if (dptr)
return(dptr->path);
return(NULL);
}
/****************************************************************************
- Get the dir wcard for a dir index (lanman2 specific).
+ Get the dir wcard for a dir index.
****************************************************************************/
char *dptr_wcard(int key)
{
- dptr_struct *dptr = dptr_get(key, False);
-
+ struct dptr_struct *dptr = dptr_get(key, False);
if (dptr)
return(dptr->wcard);
return(NULL);
}
/****************************************************************************
- Set the dir wcard for a dir index (lanman2 specific).
- Returns 0 on ok, 1 on fail.
+ Get the dir attrib for a dir index.
****************************************************************************/
-BOOL dptr_set_wcard(int key, char *wcard)
+uint16 dptr_attr(int key)
{
- dptr_struct *dptr = dptr_get(key, False);
-
- if (dptr) {
- dptr->wcard = wcard;
- return True;
- }
- return False;
+ struct dptr_struct *dptr = dptr_get(key, False);
+ if (dptr)
+ return(dptr->attr);
+ return(0);
}
/****************************************************************************
- Set the dir attrib for a dir index (lanman2 specific).
+ Set the dir wcard for a dir index.
Returns 0 on ok, 1 on fail.
****************************************************************************/
-BOOL dptr_set_attr(int key, uint16 attr)
+BOOL dptr_set_wcard_and_attributes(int key, char *wcard, uint16 attr)
{
- dptr_struct *dptr = dptr_get(key, False);
+ struct dptr_struct *dptr = dptr_get(key, False);
if (dptr) {
dptr->attr = attr;
+ dptr->wcard = wcard;
+ dptr->has_wild = ms_has_wild(wcard);
return True;
}
return False;
}
/****************************************************************************
- Get the dir attrib for a dir index (lanman2 specific)
-****************************************************************************/
-
-uint16 dptr_attr(int key)
-{
- dptr_struct *dptr = dptr_get(key, False);
-
- if (dptr)
- return(dptr->attr);
- return(0);
-}
-
-/****************************************************************************
Close a dptr (internal func).
****************************************************************************/
-static void dptr_close_internal(dptr_struct *dptr)
+static void dptr_close_internal(struct dptr_struct *dptr)
{
DEBUG(4,("closing dptr key %d\n",dptr->dnum));
@@ -237,9 +231,8 @@ static void dptr_close_internal(dptr_struct *dptr)
bitmap_clear(dptr_bmap, dptr->dnum - 1);
- if (dptr->ptr) {
- CloseDir(dptr->ptr);
- dptrs_open--;
+ if (dptr->dir_hnd) {
+ CloseDir(dptr->dir_hnd);
}
/* Lanman 2 specific code */
@@ -254,14 +247,14 @@ static void dptr_close_internal(dptr_struct *dptr)
void dptr_close(int *key)
{
- dptr_struct *dptr;
+ struct dptr_struct *dptr;
if(*key == INVALID_DPTR_KEY)
return;
/* OS/2 seems to use -1 to indicate "close all directories" */
if (*key == -1) {
- dptr_struct *next;
+ struct dptr_struct *next;
for(dptr = dirptrs; dptr; dptr = next) {
next = dptr->next;
dptr_close_internal(dptr);
@@ -288,7 +281,7 @@ void dptr_close(int *key)
void dptr_closecnum(connection_struct *conn)
{
- dptr_struct *dptr, *next;
+ struct dptr_struct *dptr, *next;
for(dptr = dirptrs; dptr; dptr = next) {
next = dptr->next;
if (dptr->conn == conn)
@@ -302,9 +295,9 @@ void dptr_closecnum(connection_struct *conn)
void dptr_idlecnum(connection_struct *conn)
{
- dptr_struct *dptr;
+ struct dptr_struct *dptr;
for(dptr = dirptrs; dptr; dptr = dptr->next) {
- if (dptr->conn == conn && dptr->ptr)
+ if (dptr->conn == conn && dptr->dir_hnd)
dptr_idle(dptr);
}
}
@@ -315,7 +308,7 @@ void dptr_idlecnum(connection_struct *conn)
void dptr_closepath(char *path,uint16 spid)
{
- dptr_struct *dptr, *next;
+ struct dptr_struct *dptr, *next;
for(dptr = dirptrs; dptr; dptr = next) {
next = dptr->next;
if (spid == dptr->spid && strequal(dptr->path,path))
@@ -324,35 +317,6 @@ void dptr_closepath(char *path,uint16 spid)
}
/****************************************************************************
- Start a directory listing.
-****************************************************************************/
-
-static BOOL start_dir(connection_struct *conn, pstring directory)
-{
- const char *dir2;
-
- DEBUG(5,("start_dir dir=%s\n",directory));
-
- if (!check_name(directory,conn))
- return(False);
-
- /* use a const pointer from here on */
- dir2 = directory;
-
- if (! *dir2)
- dir2 = ".";
-
- conn->dirptr = OpenDir(conn, directory, True);
- if (conn->dirptr) {
- dptrs_open++;
- string_set(&conn->dirpath,directory);
- return(True);
- }
-
- return(False);
-}
-
-/****************************************************************************
Try and close the oldest handle not marked for
expect close in the hope that the client has
finished with that one.
@@ -360,7 +324,7 @@ static BOOL start_dir(connection_struct *conn, pstring directory)
static void dptr_close_oldest(BOOL old)
{
- dptr_struct *dptr;
+ struct dptr_struct *dptr;
/*
* Go to the end of the list.
@@ -393,23 +357,39 @@ static void dptr_close_oldest(BOOL old)
from the bitmap range 0 - 255 as old SMBsearch directory handles are only
one byte long. If old_handle is false we allocate from the range
256 - MAX_DIRECTORY_HANDLES. We bias the number we return by 1 to ensure
- a directory handle is never zero. All the above is folklore taught to
- me at Andrew's knee.... :-) :-). JRA.
+ a directory handle is never zero.
****************************************************************************/
int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid)
{
- dptr_struct *dptr;
+ struct dptr_struct *dptr = NULL;
+ struct smb_Dir *dir_hnd;
+ const char *dir2;
+
+ DEBUG(5,("dptr_create dir=%s\n", path));
- if (!start_dir(conn,path))
+ if (!check_name(path,conn))
return(-2); /* Code to say use a unix error return code. */
+ /* use a const pointer from here on */
+ dir2 = path;
+ if (!*dir2)
+ dir2 = ".";
+
+ dir_hnd = OpenDir(conn, dir2, True);
+ if (!dir_hnd) {
+ return (-2);
+ }
+
+ string_set(&conn->dirpath,dir2);
+
if (dptrs_open >= MAX_OPEN_DIRECTORIES)
dptr_idleoldest();
- dptr = SMB_MALLOC_P(dptr_struct);
+ dptr = SMB_MALLOC_P(struct dptr_struct);
if(!dptr) {
DEBUG(0,("malloc fail in dptr_create.\n"));
+ CloseDir(dir_hnd);
return -1;
}
@@ -439,6 +419,7 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp
if(dptr->dnum == -1 || dptr->dnum > 254) {
DEBUG(0,("dptr_create: returned %d: Error - all old dirptrs in use ?\n", dptr->dnum));
SAFE_FREE(dptr);
+ CloseDir(dir_hnd);
return -1;
}
}
@@ -468,6 +449,7 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp
if(dptr->dnum == -1 || dptr->dnum < 255) {
DEBUG(0,("dptr_create: returned %d: Error - all new dirptrs in use ?\n", dptr->dnum));
SAFE_FREE(dptr);
+ CloseDir(dir_hnd);
return -1;
}
}
@@ -477,22 +459,55 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp
dptr->dnum += 1; /* Always bias the dnum by one - no zero dnums allowed. */
- dptr->ptr = conn->dirptr;
- string_set(&dptr->path,path);
+ string_set(&dptr->path,dir2);
dptr->conn = conn;
+ dptr->dir_hnd = dir_hnd;
dptr->spid = spid;
dptr->expect_close = expect_close;
dptr->wcard = NULL; /* Only used in lanman2 searches */
dptr->attr = 0; /* Only used in lanman2 searches */
+ dptr->has_wild = True; /* Only used in lanman2 searches */
DLIST_ADD(dirptrs, dptr);
DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n",
dptr->dnum,path,expect_close));
+ conn->dirptr = dptr;
+
return(dptr->dnum);
}
+
+/****************************************************************************
+ Wrapper functions to access the lower level directory handles.
+****************************************************************************/
+
+int dptr_CloseDir(struct dptr_struct *dptr)
+{
+ return CloseDir(dptr->dir_hnd);
+}
+
+const char *dptr_ReadDirName(struct dptr_struct *dptr, long *poffset)
+{
+ return ReadDirName(dptr->dir_hnd, poffset);
+}
+
+void dptr_SeekDir(struct dptr_struct *dptr, long offset)
+{
+ SeekDir(dptr->dir_hnd, offset);
+}
+
+long dptr_TellDir(struct dptr_struct *dptr)
+{
+ return TellDir(dptr->dir_hnd);
+}
+
+BOOL dptr_SearchDir(struct dptr_struct *dptr, const char *name, long *poffset, BOOL case_sensitive)
+{
+ return SearchDir(dptr->dir_hnd, name, poffset, case_sensitive);
+}
+
/****************************************************************************
Fill the 5 byte server reserved dptr field.
****************************************************************************/
@@ -500,15 +515,15 @@ int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL exp
BOOL dptr_fill(char *buf1,unsigned int key)
{
unsigned char *buf = (unsigned char *)buf1;
- void *p = dptr_ptr(key);
+ struct dptr_struct *dptr = dptr_get(key, False);
uint32 offset;
- if (!p) {
+ if (!dptr) {
DEBUG(1,("filling null dirptr %d\n",key));
return(False);
}
- offset = TellDir(p);
+ offset = TellDir(dptr->dir_hnd);
DEBUG(6,("fill on key %u dirptr 0x%lx now at %d\n",key,
- (long)p,(int)offset));
+ (long)dptr->dir_hnd,(int)offset));
buf[0] = key;
SIVAL(buf,1,offset | DPTR_MASK);
return(True);
@@ -518,38 +533,38 @@ BOOL dptr_fill(char *buf1,unsigned int key)
Fetch the dir ptr and seek it given the 5 byte server field.
****************************************************************************/
-void *dptr_fetch(char *buf,int *num)
+struct dptr_struct *dptr_fetch(char *buf,int *num)
{
unsigned int key = *(unsigned char *)buf;
- void *p = dptr_ptr(key);
+ struct dptr_struct *dptr = dptr_get(key, False);
uint32 offset;
- if (!p) {
+ if (!dptr) {
DEBUG(3,("fetched null dirptr %d\n",key));
return(NULL);
}
*num = key;
offset = IVAL(buf,1)&~DPTR_MASK;
- SeekDir(p,offset);
+ SeekDir(dptr->dir_hnd,(long)offset);
DEBUG(3,("fetching dirptr %d for path %s at offset %d\n",
key,dptr_path(key),offset));
- return(p);
+ return(dptr);
}
/****************************************************************************
Fetch the dir ptr.
****************************************************************************/
-void *dptr_fetch_lanman2(int dptr_num)
+struct dptr_struct *dptr_fetch_lanman2(int dptr_num)
{
- void *p = dptr_ptr(dptr_num);
+ struct dptr_struct *dptr = dptr_get(dptr_num, False);
- if (!p) {
+ if (!dptr) {
DEBUG(3,("fetched null dirptr %d\n",dptr_num));
return(NULL);
}
DEBUG(3,("fetching dirptr %d for path %s\n",dptr_num,dptr_path(dptr_num)));
- return(p);
+ return(dptr);
}
/****************************************************************************
@@ -612,11 +627,11 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype, pstring fname
return(False);
while (!found) {
- long curoff = TellDir(conn->dirptr);
- dname = ReadDirName(conn->dirptr, &curoff);
+ long curoff = TellDir(conn->dirptr->dir_hnd);
+ dname = ReadDirName(conn->dirptr->dir_hnd, &curoff);
DEBUG(6,("readdir on dirptr 0x%lx now at offset %ld\n",
- (long)conn->dirptr,TellDir(conn->dirptr)));
+ (long)conn->dirptr,TellDir(conn->dirptr->dir_hnd)));
if (dname == NULL)
return(False);
@@ -799,34 +814,13 @@ static BOOL file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT
return True;
}
-#define NAME_CACHE_SIZE 100
-
-struct name_cache_entry {
- char *name;
- long offset;
-};
-
-typedef struct {
- connection_struct *conn;
- DIR *dir;
- long offset;
- char *dir_path;
- struct name_cache_entry *name_cache;
- unsigned int name_cache_index;
- BOOL hide_unreadable;
- BOOL hide_unwriteable;
- BOOL hide_special;
- BOOL use_veto;
- BOOL finished;
-} Dir;
-
/*******************************************************************
Open a directory.
********************************************************************/
-void *OpenDir(connection_struct *conn, const char *name, BOOL use_veto)
+struct smb_Dir *OpenDir(connection_struct *conn, const char *name, BOOL use_veto)
{
- Dir *dirp = SMB_MALLOC_P(Dir);
+ struct smb_Dir *dirp = SMB_MALLOC_P(struct smb_Dir);
if (!dirp) {
return NULL;
}
@@ -854,7 +848,8 @@ void *OpenDir(connection_struct *conn, const char *name, BOOL use_veto)
dirp->hide_unwriteable = lp_hideunwriteable_files(SNUM(conn));
dirp->hide_special = lp_hide_special_files(SNUM(conn));
- return((void *)dirp);
+ dptrs_open++;
+ return dirp;
fail:
@@ -874,10 +869,9 @@ void *OpenDir(connection_struct *conn, const char *name, BOOL use_veto)
Close a directory.
********************************************************************/
-int CloseDir(void *p)
+int CloseDir(struct smb_Dir *dirp)
{
int i, ret = 0;
- Dir *dirp = (Dir *)p;
if (dirp->dir) {
ret = SMB_VFS_CLOSEDIR(dirp->conn,dirp->dir);
@@ -890,62 +884,20 @@ int CloseDir(void *p)
}
SAFE_FREE(dirp->name_cache);
SAFE_FREE(dirp);
+ dptrs_open--;
return ret;
}
/*******************************************************************
- Set a directory into an inactive state.
-********************************************************************/
-
-static void SleepDir(Dir *dirp)
-{
- if (dirp->dir) {
- SMB_VFS_CLOSEDIR(dirp->conn,dirp->dir);
- dirp->dir = 0;
- }
- dirp->offset = 0;
-}
-
-/*******************************************************************
- Wake a directory into a known state.
-********************************************************************/
-
-static int WakeDir(Dir *dirp, long offset)
-{
- if (!dirp->dir) {
- dirp->dir = SMB_VFS_OPENDIR(dirp->conn, dirp->dir_path);
- if (!dirp->dir) {
- DEBUG(0,("WakeDir: Can't open %s. %s\n", dirp->dir_path, strerror(errno) ));
- dirp->finished = True;
- return -1;
- }
- }
- if (offset != dirp->offset) {
- SMB_VFS_SEEKDIR(dirp->conn, dirp->dir, offset);
- dirp->offset = SMB_VFS_TELLDIR(dirp->conn, dirp->dir);
- if (dirp->offset != offset) {
- DEBUG(0,("WakeDir: in path %s. offset changed %ld -> %ld\n",
- dirp->dir_path, offset, dirp->offset ));
- return -1;
- }
- }
- return 0;
-}
-
-/*******************************************************************
Read from a directory. Also return current offset.
********************************************************************/
-const char *ReadDirName(void *p, long *poffset)
+const char *ReadDirName(struct smb_Dir *dirp, long *poffset)
{
const char *n;
- Dir *dirp = (Dir *)p;
connection_struct *conn = dirp->conn;
- if (WakeDir(dirp, *poffset) == -1) {
- return NULL;
- }
-
+ SeekDir(dirp, *poffset);
while ((n = vfs_readdirname(conn, dirp->dir))) {
struct name_cache_entry *e;
@@ -994,9 +946,6 @@ const char *ReadDirName(void *p, long *poffset)
*poffset = e->offset= dirp->offset;
return e->name;
}
-
- dirp->finished = True;
- SleepDir(dirp);
return NULL;
}
@@ -1004,19 +953,20 @@ const char *ReadDirName(void *p, long *poffset)
Seek a dir.
********************************************************************/
-BOOL SeekDir(void *p,long offset)
+void SeekDir(struct smb_Dir *dirp, long offset)
{
- Dir *dirp = (Dir *)p;
- return (WakeDir(dirp, offset) != -1);
+ if (offset != dirp->offset) {
+ SMB_VFS_SEEKDIR(dirp->conn, dirp->dir, offset);
+ dirp->offset = offset;
+ }
}
/*******************************************************************
Tell a dir position.
********************************************************************/
-long TellDir(void *p)
+long TellDir(struct smb_Dir *dirp)
{
- Dir *dirp = (Dir *)p;
return(dirp->offset);
}
@@ -1024,24 +974,18 @@ long TellDir(void *p)
Find an entry by name. Leave us at the offset after it.
********************************************************************/
-BOOL SearchDir(void *p, const char *name, long *poffset, BOOL case_sensitive)
+BOOL SearchDir(struct smb_Dir *dirp, const char *name, long *poffset, BOOL case_sensitive)
{
int i;
- Dir *dirp = (Dir *)p;
const char *entry;
connection_struct *conn = dirp->conn;
- /* Re-create dir but don't seek. */
- if (WakeDir(dirp, dirp->offset) == -1) {
- return False;
- }
-
/* Search back in the name cache. */
for (i = dirp->name_cache_index; i >= 0; i--) {
struct name_cache_entry *e = &dirp->name_cache[i];
if (e->name && (case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
*poffset = e->offset;
- WakeDir(dirp, e->offset);
+ SeekDir(dirp, e->offset);
return True;
}
}
@@ -1049,7 +993,7 @@ BOOL SearchDir(void *p, const char *name, long *poffset, BOOL case_sensitive)
struct name_cache_entry *e = &dirp->name_cache[i];
if (e->name && (case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
*poffset = e->offset;
- WakeDir(dirp, e->offset);
+ SeekDir(dirp, e->offset);
return True;
}
}
@@ -1062,7 +1006,5 @@ BOOL SearchDir(void *p, const char *name, long *poffset, BOOL case_sensitive)
return True;
}
}
-
- SleepDir(dirp);
return False;
}