Unix SMB/Netbios implementation.
Version 1.9.
Directory handling routines
- Copyright (C) Andrew Tridgell 1992-1995
+ Copyright (C) Andrew Tridgell 1992-1997
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
*/
#include "includes.h"
-#include "loadparm.h"
extern int DEBUGLEVEL;
extern connection_struct Connections[];
****************************************************************************/
static void *dptr_get(int key,uint32 lastused)
{
- if (dirptrs[key].valid) {
- if (lastused) dirptrs[key].lastused = lastused;
- if (!dirptrs[key].ptr) {
+ struct dptr_struct *dp = &dirptrs[key];
+
+ if (dp->valid) {
+ if (lastused) dp->lastused = lastused;
+ if (!dp->ptr) {
if (dptrs_open >= MAXDIR)
dptr_idleoldest();
DEBUG(4,("Reopening dptr key %d\n",key));
- if ((dirptrs[key].ptr = OpenDir(dirptrs[key].path)))
+ if ((dp->ptr = OpenDir(dp->cnum, dp->path, True)))
dptrs_open++;
}
- return(dirptrs[key].ptr);
+ return(dp->ptr);
}
return(NULL);
}
if (! *directory)
directory = ".";
- Connections[cnum].dirptr = OpenDir(directory);
+ Connections[cnum].dirptr = OpenDir(cnum, directory, True);
if (Connections[cnum].dirptr) {
dptrs_open++;
string_set(&Connections[cnum].dirpath,directory);
int oldi;
if (!start_dir(cnum,path))
- return(-1);
+ return(-2); /* Code to say use a unix error return code. */
if (dptrs_open >= MAXDIR)
dptr_idleoldest();
BOOL isrootdir;
pstring filename;
BOOL matched;
+ BOOL needslash;
*path = *pathreal = *filename = 0;
strequal(Connections[cnum].dirpath,".") ||
strequal(Connections[cnum].dirpath,"/"));
+ needslash =
+ ( Connections[cnum].dirpath[strlen(Connections[cnum].dirpath) -1] != '/');
+
if (!Connections[cnum].dirptr)
return(False);
matched = False;
- strcpy(filename,dname);
+ pstrcpy(filename,dname);
if ((strcmp(filename,mask) == 0) ||
(name_map_mangle(filename,True,SNUM(cnum)) &&
if (isrootdir && (strequal(filename,"..") || strequal(filename,".")))
continue;
- strcpy(fname,filename);
+ pstrcpy(fname,filename);
*path = 0;
- strcpy(path,Connections[cnum].dirpath);
- strcat(path,"/");
- strcpy(pathreal,path);
+ pstrcpy(path,Connections[cnum].dirpath);
+ if(needslash)
+ strcat(path,"/");
+ pstrcpy(pathreal,path);
strcat(path,fname);
strcat(pathreal,dname);
if (sys_stat(pathreal,&sbuf) != 0)
/*******************************************************************
open a directory
********************************************************************/
-void *OpenDir(char *name)
+void *OpenDir(int cnum, char *name, BOOL use_veto)
{
Dir *dirp;
char *n;
dirp->pos = dirp->numentries = dirp->mallocsize = 0;
dirp->data = dirp->current = NULL;
- while ((n = readdirname(p))) {
+ while ((n = readdirname(p)))
+ {
int l = strlen(n)+1;
+
+ /* If it's a vetoed file, pretend it doesn't even exist */
+ if (use_veto && IS_VETO_PATH(cnum, n)) continue;
+
if (used + l > dirp->mallocsize) {
int s = MAX(used+l,used+2000);
char *r;
}
-static int dir_cache_size = 0;
-static struct dir_cache {
- struct dir_cache *next;
- struct dir_cache *prev;
- char *path;
- char *name;
- char *dname;
- int snum;
-} *dir_cache = NULL;
+/* -------------------------------------------------------------------------- **
+ * This section manages a global directory cache.
+ * (It should probably be split into a separate module. crh)
+ * -------------------------------------------------------------------------- **
+ */
-/*******************************************************************
-add an entry to the directory cache
-********************************************************************/
-void DirCacheAdd(char *path,char *name,char *dname,int snum)
-{
- struct dir_cache *entry = (struct dir_cache *)malloc(sizeof(*entry));
- if (!entry) return;
- entry->path = strdup(path);
- entry->name = strdup(name);
- entry->dname = strdup(dname);
- entry->snum = snum;
- if (!entry->path || !entry->name || !entry->dname) return;
-
- entry->next = dir_cache;
- entry->prev = NULL;
- if (entry->next) entry->next->prev = entry;
- dir_cache = entry;
-
- DEBUG(4,("Added dir cache entry %s %s -> %s\n",path,name,dname));
-
- if (dir_cache_size == DIRCACHESIZE) {
- for (entry=dir_cache; entry->next; entry=entry->next) ;
- free(entry->path);
- free(entry->name);
- free(entry->dname);
- if (entry->prev) entry->prev->next = entry->next;
- free(entry);
- } else {
- dir_cache_size++;
- }
-}
+#include "ubi_dLinkList.h"
+typedef struct
+ {
+ ubi_dlNode node;
+ char *path;
+ char *name;
+ char *dname;
+ int snum;
+ } dir_cache_entry;
+
+static ubi_dlList dir_cache[1] = { { NULL, NULL, 0 } };
+
+void DirCacheAdd( char *path, char *name, char *dname, int snum )
+ /* ------------------------------------------------------------------------ **
+ * Add an entry to the directory cache.
+ *
+ * Input: path -
+ * name -
+ * dname -
+ * snum -
+ *
+ * Output: None.
+ *
+ * ------------------------------------------------------------------------ **
+ */
+ {
+ int pathlen;
+ int namelen;
+ dir_cache_entry *entry;
+
+ /* Allocate the structure & string space in one go so that it can be freed
+ * in one call to free().
+ */
+ pathlen = strlen( path ) +1; /* Bytes required to store path (with nul). */
+ namelen = strlen( name ) +1; /* Bytes required to store name (with nul). */
+ entry = (dir_cache_entry *)malloc( sizeof( dir_cache_entry )
+ + pathlen
+ + namelen
+ + strlen( dname ) +1 );
+ if( NULL == entry ) /* Not adding to the cache is not fatal, */
+ return; /* so just return as if nothing happened. */
+
+ /* Set pointers correctly and load values. */
+ entry->path = strcpy( (char *)&entry[1], path);
+ entry->name = strcpy( &(entry->path[pathlen]), name);
+ entry->dname = strcpy( &(entry->name[namelen]), dname);
+ entry->snum = snum;
+
+ /* Add the new entry to the linked list. */
+ (void)ubi_dlAddHead( dir_cache, entry );
+ DEBUG( 4, ("Added dir cache entry %s %s -> %s\n", path, name, dname ) );
+
+ /* Free excess cache entries. */
+ while( DIRCACHESIZE < dir_cache->count )
+ free( ubi_dlRemTail( dir_cache ) );
+
+ } /* DirCacheAdd */
+
+
+char *DirCacheCheck( char *path, char *name, int snum )
+ /* ------------------------------------------------------------------------ **
+ * Search for an entry to the directory cache.
+ *
+ * Input: path -
+ * name -
+ * snum -
+ *
+ * Output: The dname string of the located entry, or NULL if the entry was
+ * not found.
+ *
+ * Notes: This uses a linear search, which is is okay because of
+ * the small size of the cache. Use a splay tree or hash
+ * for large caches.
+ *
+ * ------------------------------------------------------------------------ **
+ */
+ {
+ dir_cache_entry *entry;
-/*******************************************************************
-check for an entry in the directory cache
-********************************************************************/
-char *DirCacheCheck(char *path,char *name,int snum)
-{
- struct dir_cache *entry;
-
- for (entry=dir_cache; entry; entry=entry->next) {
- if (entry->snum == snum &&
- strcmp(path,entry->path) == 0 &&
- strcmp(name,entry->name) == 0) {
- DEBUG(4,("Got dir cache hit on %s %s -> %s\n",path,name,entry->dname));
- return(entry->dname);
+ for( entry = (dir_cache_entry *)ubi_dlFirst( dir_cache );
+ NULL != entry;
+ entry = (dir_cache_entry *)ubi_dlNext( entry ) )
+ {
+ if( entry->snum == snum
+ && 0 == strcmp( name, entry->name )
+ && 0 == strcmp( path, entry->path ) )
+ {
+ DEBUG(4, ("Got dir cache hit on %s %s -> %s\n",path,name,entry->dname));
+ return( entry->dname );
+ }
}
- }
return(NULL);
-}
+ } /* DirCacheCheck */
+
+void DirCacheFlush( int snum )
+ /* ------------------------------------------------------------------------ **
+ * Remove all cache entries which have an snum that matches the input.
+ *
+ * Input: snum -
+ *
+ * Output: None.
+ *
+ * ------------------------------------------------------------------------ **
+ */
+ {
+ dir_cache_entry *entry;
+ ubi_dlNodePtr next;
-/*******************************************************************
-flush entries in the dir_cache
-********************************************************************/
-void DirCacheFlush(int snum)
-{
- struct dir_cache *entry,*next;
-
- for (entry=dir_cache; entry; entry=next) {
- if (entry->snum == snum) {
- free(entry->path);
- free(entry->dname);
- free(entry->name);
- next = entry->next;
- if (entry->prev) entry->prev->next = entry->next;
- if (entry->next) entry->next->prev = entry->prev;
- if (dir_cache == entry) dir_cache = entry->next;
- free(entry);
- } else {
- next = entry->next;
+ for( entry = (dir_cache_entry *)ubi_dlFirst( dir_cache ); NULL != entry; )
+ {
+ next = ubi_dlNext( entry );
+ if( entry->snum == snum )
+ free( ubi_dlRemThis( dir_cache, entry ) );
+ entry = (dir_cache_entry *)next;
}
- }
-}
+ } /* DirCacheFlush */
+
+/* -------------------------------------------------------------------------- **
+ * End of the section that manages the global directory cache.
+ * -------------------------------------------------------------------------- **
+ */
#ifdef REPLACE_GETWD