summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>1999-01-06 02:18:57 +0000
committerJeremy Allison <jra@samba.org>1999-01-06 02:18:57 +0000
commite8344156bb9d161235d40755635f5bbdd3916ef1 (patch)
tree89578403f90f20004ba183dd2d59241ab6560ff2
parent5a71a6c96f1b2208a302b974f8274fae1e98b546 (diff)
downloadsamba-e8344156bb9d161235d40755635f5bbdd3916ef1.tar.gz
samba-e8344156bb9d161235d40755635f5bbdd3916ef1.tar.xz
samba-e8344156bb9d161235d40755635f5bbdd3916ef1.zip
Converted the code in smbd/dir.c to use bitmaps instead of a static
array for directory handles. This tidied up the code a *lot*. Plus it means I've fixed the bug in PR#10058, which was due to an NT app that wanted to simultaneously open >256 directory handles. Jeremy.
-rw-r--r--source/include/local.h5
-rw-r--r--source/include/proto.h13
-rw-r--r--source/lib/debug.c4
-rw-r--r--source/smbd/dir.c424
4 files changed, 255 insertions, 191 deletions
diff --git a/source/include/local.h b/source/include/local.h
index 3261da1cdc3..6aef7f0b8dd 100644
--- a/source/include/local.h
+++ b/source/include/local.h
@@ -34,6 +34,11 @@
file handle per directory, but large numbers do use more memory */
#define MAX_OPEN_DIRECTORIES 64
+/* max number of directory handles */
+/* As this now uses the bitmap code this can be
+ quite large. */
+#define MAX_DIRECTORY_HANDLES 2048
+
/* define what facility to use for syslog */
#ifndef SYSLOG_FACILITY
#define SYSLOG_FACILITY LOG_DAEMON
diff --git a/source/include/proto.h b/source/include/proto.h
index 1f4f522ac77..72baf1c77ec 100644
--- a/source/include/proto.h
+++ b/source/include/proto.h
@@ -2412,10 +2412,6 @@ int reply_negprot(connection_struct *conn,
char *inbuf,char *outbuf, int dum_size,
int dum_buffsize);
-/*The following definitions come from smbd/noquotas.c */
-
-BOOL disk_quotas(char *path,SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize);
-
/*The following definitions come from smbd/nttrans.c */
void fail_next_srvsvc_open(void);
@@ -2510,6 +2506,15 @@ void construct_reply_common(char *inbuf,char *outbuf);
int chain_reply(char *inbuf,char *outbuf,int size,int bufsize);
void smbd_process(void);
+/*The following definitions come from smbd/quotas.c */
+
+BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize);
+BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize);
+BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize);
+BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize);
+BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize);
+BOOL disk_quotas(char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize);
+
/*The following definitions come from smbd/reply.c */
int reply_special(char *inbuf,char *outbuf);
diff --git a/source/lib/debug.c b/source/lib/debug.c
index 02e50aa9213..859fadcafce 100644
--- a/source/lib/debug.c
+++ b/source/lib/debug.c
@@ -112,7 +112,7 @@ static int debug_count = 0;
static int syslog_level = 0;
#endif
static pstring format_bufr = { '\0' };
-static int format_pos = 0;
+static size_t format_pos = 0;
/* -------------------------------------------------------------------------- **
@@ -428,7 +428,7 @@ static void bufr_print( void )
*/
static void format_debug_text( char *msg )
{
- int i;
+ size_t i;
BOOL timestamp = (!stdout_logging && (lp_timestamp_logs() ||
!(lp_loaded())));
diff --git a/source/smbd/dir.c b/source/smbd/dir.c
index dcf1d158b4c..8eea7c76962 100644
--- a/source/smbd/dir.c
+++ b/source/smbd/dir.c
@@ -27,257 +27,321 @@ extern int DEBUGLEVEL;
This module implements directory related functions for Samba.
*/
-
-
-static uint32 dircounter = 0;
-
-
-#define NUMDIRPTRS 256
-
-
-static struct dptr_struct {
+typedef struct _dptr_struct {
+ struct _dptr_struct *next, *prev;
+ int dnum;
int pid;
connection_struct *conn;
- uint32 lastused;
void *ptr;
- BOOL valid;
BOOL finished;
BOOL expect_close;
char *wcard; /* Field only used for trans2_ searches */
uint16 attr; /* Field only used for trans2_ searches */
char *path;
-}
-dirptrs[NUMDIRPTRS];
+} dptr_struct;
+static struct bitmap *dptr_bmap;
+static dptr_struct *dirptrs;
static int dptrs_open = 0;
/****************************************************************************
-initialise the dir array
+ Initialise the dir bitmap.
****************************************************************************/
+
void init_dptrs(void)
{
static BOOL dptrs_init=False;
- int i;
- if (dptrs_init) return;
- for (i=0;i<NUMDIRPTRS;i++)
- {
- dirptrs[i].valid = False;
- dirptrs[i].wcard = NULL;
- dirptrs[i].ptr = NULL;
- string_init(&dirptrs[i].path,"");
- }
+ if (dptrs_init)
+ return;
+
+ dptr_bmap = bitmap_allocate(MAX_DIRECTORY_HANDLES);
+
+ if (!dptr_bmap)
+ exit_server("out of memory in init_dptrs\n");
+
dptrs_init = True;
}
/****************************************************************************
-idle a dptr - the directory is closed but the control info is kept
+ Idle a dptr - the directory is closed but the control info is kept.
****************************************************************************/
-static void dptr_idle(int key)
+
+static void dptr_idle(dptr_struct *dptr)
{
- if (dirptrs[key].valid && dirptrs[key].ptr) {
- DEBUG(4,("Idling dptr key %d\n",key));
+ if (dptr->ptr) {
+ DEBUG(4,("Idling dptr dnum %d\n",dptr->dnum));
dptrs_open--;
- CloseDir(dirptrs[key].ptr);
- dirptrs[key].ptr = NULL;
- }
+ CloseDir(dptr->ptr);
+ dptr->ptr = NULL;
+ }
}
/****************************************************************************
-idle the oldest dptr
+ Idle the oldest dptr.
****************************************************************************/
+
static void dptr_idleoldest(void)
{
- int i;
- uint32 old=dircounter+1;
- int oldi= -1;
- for (i=0;i<NUMDIRPTRS;i++)
- if (dirptrs[i].valid && dirptrs[i].ptr && dirptrs[i].lastused < old) {
- old = dirptrs[i].lastused;
- oldi = i;
- }
- if (oldi != -1)
- dptr_idle(oldi);
- else
+ dptr_struct *dptr;
+
+ /*
+ * Go to the end of the list.
+ */
+ for(dptr = dirptrs; dptr && dptr->next; dptr = dptr->next)
+ ;
+
+ if(!dptr) {
DEBUG(0,("No dptrs available to idle??\n"));
+ return;
+ }
+
+ /*
+ * Now walk back until we find a non-idle ptr.
+ */
+
+ for(; dptr; dptr = dptr->prev) {
+ if (dptr->ptr)
+ dptr_idle(dptr);
+ }
}
/****************************************************************************
-get the dir ptr for a dir index
+ Get the dptr_struct for a dir index.
****************************************************************************/
-static void *dptr_get(int key,uint32 lastused)
+
+static dptr_struct *dptr_get(int key)
{
- struct dptr_struct *dp = &dirptrs[key];
-
- if (dp->valid) {
- if (lastused) dp->lastused = lastused;
- if (!dp->ptr) {
- if (dptrs_open >= MAX_OPEN_DIRECTORIES)
- dptr_idleoldest();
- DEBUG(4,("Reopening dptr key %d\n",key));
- if ((dp->ptr = OpenDir(dp->conn, dp->path, True)))
- dptrs_open++;
- }
- return(dp->ptr);
- }
- return(NULL);
+ dptr_struct *dptr;
+
+ for(dptr = dirptrs; dptr; dptr = dptr->next) {
+ if(dptr->dnum == key) {
+ if (!dptr->ptr) {
+ 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++;
+ }
+ DLIST_PROMOTE(dirptrs,dptr);
+ return dptr;
+ }
+ }
+ return(NULL);
+}
+
+/****************************************************************************
+ Get the dptr ptr for a dir index.
+****************************************************************************/
+
+static void *dptr_ptr(int key)
+{
+ dptr_struct *dptr = dptr_get(key);
+
+ if (dptr)
+ return(dptr->ptr);
+ return(NULL);
}
/****************************************************************************
-get the dir path for a dir index
+ Get the dir path for a dir index.
****************************************************************************/
+
char *dptr_path(int key)
{
- if (dirptrs[key].valid)
- return(dirptrs[key].path);
+ dptr_struct *dptr = dptr_get(key);
+
+ 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 (lanman2 specific).
****************************************************************************/
+
char *dptr_wcard(int key)
{
- if (dirptrs[key].valid)
- return(dirptrs[key].wcard);
+ dptr_struct *dptr = dptr_get(key);
+
+ if (dptr)
+ return(dptr->wcard);
return(NULL);
}
/****************************************************************************
-set the dir wcard for a dir index (lanman2 specific)
-Returns 0 on ok, 1 on fail.
+ Set the dir wcard for a dir index (lanman2 specific).
+ Returns 0 on ok, 1 on fail.
****************************************************************************/
+
BOOL dptr_set_wcard(int key, char *wcard)
{
- if (dirptrs[key].valid) {
- dirptrs[key].wcard = wcard;
+ dptr_struct *dptr = dptr_get(key);
+
+ if (dptr) {
+ dptr->wcard = wcard;
return True;
}
return False;
}
/****************************************************************************
-set the dir attrib for a dir index (lanman2 specific)
-Returns 0 on ok, 1 on fail.
+ Set the dir attrib for a dir index (lanman2 specific).
+ Returns 0 on ok, 1 on fail.
****************************************************************************/
+
BOOL dptr_set_attr(int key, uint16 attr)
{
- if (dirptrs[key].valid) {
- dirptrs[key].attr = attr;
+ dptr_struct *dptr = dptr_get(key);
+
+ if (dptr) {
+ dptr->attr = attr;
return True;
}
return False;
}
/****************************************************************************
-get the dir attrib for a dir index (lanman2 specific)
+ Get the dir attrib for a dir index (lanman2 specific)
****************************************************************************/
+
uint16 dptr_attr(int key)
{
- if (dirptrs[key].valid)
- return(dirptrs[key].attr);
+ dptr_struct *dptr = dptr_get(key);
+
+ if (dptr)
+ return(dptr->attr);
return(0);
}
/****************************************************************************
-close a dptr
+ Close a dptr (internal func).
****************************************************************************/
+
+static void dptr_close_internal(dptr_struct *dptr)
+{
+ DEBUG(4,("closing dptr key %d\n",dptr->dnum));
+
+ DLIST_REMOVE(dirptrs, dptr);
+
+ /* Free the dnum in the bitmap. */
+ bitmap_clear(dptr_bmap, dptr->dnum);
+
+ if (dptr->ptr) {
+ CloseDir(dptr->ptr);
+ dptrs_open--;
+ }
+
+ /* Lanman 2 specific code */
+ if (dptr->wcard)
+ free(dptr->wcard);
+ string_set(&dptr->path,"");
+ free((char *)dptr);
+}
+
+/****************************************************************************
+ Close a dptr given a key.
+****************************************************************************/
+
void dptr_close(int key)
{
+ dptr_struct *dptr;
+
/* OS/2 seems to use -1 to indicate "close all directories" */
if (key == -1) {
- int i;
- for (i=0;i<NUMDIRPTRS;i++)
- dptr_close(i);
+ dptr_struct *next;
+ for(dptr = dirptrs; dptr; dptr = next) {
+ next = dptr->next;
+ dptr_close_internal(dptr);
+ }
return;
}
- if (key < 0 || key >= NUMDIRPTRS) {
- DEBUG(3,("Invalid key %d given to dptr_close\n",key));
+ dptr = dptr_get(key);
+
+ if (!dptr) {
+ DEBUG(0,("Invalid key %d given to dptr_close\n",key));
return;
}
- if (dirptrs[key].valid) {
- DEBUG(4,("closing dptr key %d\n",key));
- if (dirptrs[key].ptr) {
- CloseDir(dirptrs[key].ptr);
- dptrs_open--;
- }
- /* Lanman 2 specific code */
- if (dirptrs[key].wcard)
- free(dirptrs[key].wcard);
- dirptrs[key].valid = False;
- string_set(&dirptrs[key].path,"");
- }
+ dptr_close_internal(dptr);
}
/****************************************************************************
-close all dptrs for a cnum
+ Close all dptrs for a cnum.
****************************************************************************/
+
void dptr_closecnum(connection_struct *conn)
{
- int i;
- for (i=0;i<NUMDIRPTRS;i++)
- if (dirptrs[i].valid && dirptrs[i].conn == conn)
- dptr_close(i);
+ dptr_struct *dptr, *next;
+ for(dptr = dirptrs; dptr; dptr = next) {
+ next = dptr->next;
+ if (dptr->conn == conn)
+ dptr_close_internal(dptr);
+ }
}
/****************************************************************************
-idle all dptrs for a cnum
+ Idle all dptrs for a cnum.
****************************************************************************/
+
void dptr_idlecnum(connection_struct *conn)
{
- int i;
- for (i=0;i<NUMDIRPTRS;i++)
- if (dirptrs[i].valid && dirptrs[i].conn == conn && dirptrs[i].ptr)
- dptr_idle(i);
+ dptr_struct *dptr;
+ for(dptr = dirptrs; dptr; dptr = dptr->next) {
+ if (dptr->conn == conn && dptr->ptr)
+ dptr_idle(dptr);
+ }
}
/****************************************************************************
-close a dptr that matches a given path, only if it matches the pid also
+ Close a dptr that matches a given path, only if it matches the pid also.
****************************************************************************/
+
void dptr_closepath(char *path,int pid)
{
- int i;
- for (i=0;i<NUMDIRPTRS;i++)
- if (dirptrs[i].valid && pid == dirptrs[i].pid &&
- strequal(dirptrs[i].path,path))
- dptr_close(i);
+ dptr_struct *dptr, *next;
+ for(dptr = dirptrs; dptr; dptr = next) {
+ next = dptr->next;
+ if (pid == dptr->pid && strequal(dptr->path,path))
+ dptr_close_internal(dptr);
+ }
}
/****************************************************************************
- start a directory listing
+ Start a directory listing.
****************************************************************************/
+
static BOOL start_dir(connection_struct *conn,char *directory)
{
- DEBUG(5,("start_dir dir=%s\n",directory));
+ DEBUG(5,("start_dir dir=%s\n",directory));
- if (!check_name(directory,conn))
- return(False);
+ if (!check_name(directory,conn))
+ return(False);
- if (! *directory)
- directory = ".";
-
- conn->dirptr = OpenDir(conn, directory, True);
- if (conn->dirptr) {
- dptrs_open++;
- string_set(&conn->dirpath,directory);
- return(True);
- }
+ if (! *directory)
+ directory = ".";
+
+ conn->dirptr = OpenDir(conn, directory, True);
+ if (conn->dirptr) {
+ dptrs_open++;
+ string_set(&conn->dirpath,directory);
+ return(True);
+ }
- return(False);
+ return(False);
}
/****************************************************************************
-create a new dir ptr
+ Create a new dir ptr.
****************************************************************************/
+
int dptr_create(connection_struct *conn,char *path, BOOL expect_close,int pid)
{
- int i;
- uint32 old;
- int oldi;
+ dptr_struct *dptr;
+ int dnum = -1;
if (!start_dir(conn,path))
return(-2); /* Code to say use a unix error return code. */
@@ -285,70 +349,50 @@ int dptr_create(connection_struct *conn,char *path, BOOL expect_close,int pid)
if (dptrs_open >= MAX_OPEN_DIRECTORIES)
dptr_idleoldest();
- for (i=0;i<NUMDIRPTRS;i++)
- if (!dirptrs[i].valid)
- break;
- if (i == NUMDIRPTRS) i = -1;
-
-
- /* as a 2nd option, grab the oldest not marked for expect_close */
- if (i == -1) {
- old=dircounter+1;
- oldi= -1;
- for (i=0;i<NUMDIRPTRS;i++)
- if (!dirptrs[i].expect_close && dirptrs[i].lastused < old) {
- old = dirptrs[i].lastused;
- oldi = i;
- }
- i = oldi;
+ dptr = (dptr_struct *)malloc(sizeof(dptr_struct));
+ if(!dptr) {
+ DEBUG(0,("malloc fail in dptr_create.\n"));
+ return -1;
}
- /* a 3rd option - grab the oldest one */
- if (i == -1) {
- old=dircounter+1;
- oldi= -1;
- for (i=0;i<NUMDIRPTRS;i++)
- if (dirptrs[i].lastused < old) {
- old = dirptrs[i].lastused;
- oldi = i;
- }
- i = oldi;
- }
+ ZERO_STRUCTP(dptr);
- if (i == -1) {
- DEBUG(0,("Error - all dirptrs in use??\n"));
- return(-1);
+ dptr->dnum= bitmap_find(dptr_bmap, 0);
+ if(dptr->dnum == -1) {
+ DEBUG(0,("dptr_create: Error dirptrs in use??\n"));
+ free((char *)dptr);
+ return -1;
}
- if (dirptrs[i].valid)
- dptr_close(i);
+ bitmap_set(dptr_bmap, dptr->dnum);
- dirptrs[i].ptr = conn->dirptr;
- string_set(&dirptrs[i].path,path);
- dirptrs[i].lastused = dircounter++;
- dirptrs[i].finished = False;
- dirptrs[i].conn = conn;
- dirptrs[i].pid = pid;
- dirptrs[i].expect_close = expect_close;
- dirptrs[i].wcard = NULL; /* Only used in lanman2 searches */
- dirptrs[i].attr = 0; /* Only used in lanman2 searches */
- dirptrs[i].valid = True;
+ dptr->ptr = conn->dirptr;
+ string_set(&dptr->path,path);
+ dptr->finished = False;
+ dptr->conn = conn;
+ dptr->pid = pid;
+ dptr->expect_close = expect_close;
+ dptr->wcard = NULL; /* Only used in lanman2 searches */
+ dptr->attr = 0; /* Only used in lanman2 searches */
+
+ DLIST_ADD(dirptrs, dptr);
DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n",
- i,path,expect_close));
+ dptr->dnum,path,expect_close));
- return(i);
+ return(dptr->dnum);
}
#define DPTR_MASK ((uint32)(((uint32)1)<<31))
/****************************************************************************
-fill the 5 byte server reserved dptr field
+ Fill the 5 byte server reserved dptr field.
****************************************************************************/
+
BOOL dptr_fill(char *buf1,unsigned int key)
{
unsigned char *buf = (unsigned char *)buf1;
- void *p = dptr_get(key,0);
+ void *p = dptr_ptr(key);
uint32 offset;
if (!p) {
DEBUG(1,("filling null dirptr %d\n",key));
@@ -364,20 +408,22 @@ BOOL dptr_fill(char *buf1,unsigned int key)
/****************************************************************************
-return True is the offset is at zero
+ Return True is the offset is at zero.
****************************************************************************/
+
BOOL dptr_zero(char *buf)
{
return((IVAL(buf,1)&~DPTR_MASK) == 0);
}
/****************************************************************************
-fetch the dir ptr and seek it given the 5 byte server field
+ Fetch the dir ptr and seek it given the 5 byte server field.
****************************************************************************/
+
void *dptr_fetch(char *buf,int *num)
{
unsigned int key = *(unsigned char *)buf;
- void *p = dptr_get(key,dircounter++);
+ void *p = dptr_ptr(key);
uint32 offset;
if (!p) {
DEBUG(3,("fetched null dirptr %d\n",key));
@@ -392,11 +438,12 @@ void *dptr_fetch(char *buf,int *num)
}
/****************************************************************************
-fetch the dir ptr.
+ Fetch the dir ptr.
****************************************************************************/
+
void *dptr_fetch_lanman2(int dptr_num)
{
- void *p = dptr_get(dptr_num,dircounter++);
+ void *p = dptr_ptr(dptr_num);
if (!p) {
DEBUG(3,("fetched null dirptr %d\n",dptr_num));
@@ -407,8 +454,9 @@ void *dptr_fetch_lanman2(int dptr_num)
}
/****************************************************************************
-check a filetype for being valid
+ Check a filetype for being valid.
****************************************************************************/
+
BOOL dir_check_ftype(connection_struct *conn,int mode,SMB_STRUCT_STAT *st,int dirtype)
{
if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0)
@@ -417,8 +465,9 @@ BOOL dir_check_ftype(connection_struct *conn,int mode,SMB_STRUCT_STAT *st,int di
}
/****************************************************************************
- get a directory entry
+ Get a directory entry.
****************************************************************************/
+
BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype,char *fname,
SMB_OFF_T *size,int *mode,time_t *date,BOOL check_descend)
{
@@ -512,8 +561,9 @@ typedef struct
/*******************************************************************
-open a directory
+ Open a directory.
********************************************************************/
+
void *OpenDir(connection_struct *conn, char *name, BOOL use_veto)
{
Dir *dirp;
@@ -560,8 +610,9 @@ void *OpenDir(connection_struct *conn, char *name, BOOL use_veto)
/*******************************************************************
-close a directory
+ Close a directory.
********************************************************************/
+
void CloseDir(void *p)
{
Dir *dirp = (Dir *)p;
@@ -571,8 +622,9 @@ void CloseDir(void *p)
}
/*******************************************************************
-read from a directory
+ Read from a directory.
********************************************************************/
+
char *ReadDirName(void *p)
{
char *ret;
@@ -589,8 +641,9 @@ char *ReadDirName(void *p)
/*******************************************************************
-seek a dir
+ Seek a dir.
********************************************************************/
+
BOOL SeekDir(void *p,int pos)
{
Dir *dirp = (Dir *)p;
@@ -608,8 +661,9 @@ BOOL SeekDir(void *p,int pos)
}
/*******************************************************************
-tell a dir position
+ Tell a dir position.
********************************************************************/
+
int TellDir(void *p)
{
Dir *dirp = (Dir *)p;