r25009: Large patch discussed with Volker. Move unix_convert to a talloc-based
[abartlet/samba.git/.git] / source3 / smbd / dir.c
index 30c1d77a840a80961800177ac1bf50643c67d602..e602008b8fc5af0c3c3c2adae8d25f459867e179 100644 (file)
@@ -32,8 +32,6 @@ extern struct current_user current_user;
 
 /* Make directory handle internals available. */
 
-#define NAME_CACHE_SIZE 100
-
 struct name_cache_entry {
        char *name;
        long offset;
@@ -44,6 +42,7 @@ struct smb_Dir {
        SMB_STRUCT_DIR *dir;
        long offset;
        char *dir_path;
+       size_t name_cache_size;
        struct name_cache_entry *name_cache;
        unsigned int name_cache_index;
        unsigned int file_number;
@@ -381,12 +380,11 @@ static void dptr_close_oldest(BOOL old)
  wcard must not be zero.
 ****************************************************************************/
 
-NTSTATUS dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid,
+NTSTATUS dptr_create(connection_struct *conn, const char *path, BOOL old_handle, BOOL expect_close,uint16 spid,
                const char *wcard, BOOL wcard_has_wild, uint32 attr, struct dptr_struct **dptr_ret)
 {
        struct dptr_struct *dptr = NULL;
        struct smb_Dir *dir_hnd;
-        const char *dir2;
        NTSTATUS status;
 
        DEBUG(5,("dptr_create dir=%s\n", path));
@@ -400,17 +398,12 @@ NTSTATUS dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOO
                return status;
        }
 
-       /* use a const pointer from here on */
-       dir2 = path;
-       if (!*dir2)
-               dir2 = ".";
-
-       dir_hnd = OpenDir(conn, dir2, wcard, attr);
+       dir_hnd = OpenDir(conn, path, wcard, attr);
        if (!dir_hnd) {
                return map_nt_error_from_unix(errno);
        }
 
-       string_set(&conn->dirpath,dir2);
+       string_set(&conn->dirpath,path);
 
        if (dirhandles_open >= MAX_OPEN_DIRECTORIES) {
                dptr_idleoldest();
@@ -489,7 +482,7 @@ NTSTATUS dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOO
 
        dptr->dnum += 1; /* Always bias the dnum by one - no zero dnums allowed. */
 
-       string_set(&dptr->path,dir2);
+       string_set(&dptr->path,path);
        dptr->conn = conn;
        dptr->dir_hnd = dir_hnd;
        dptr->spid = spid;
@@ -759,10 +752,15 @@ BOOL dir_check_ftype(connection_struct *conn, uint32 mode, uint32 dirtype)
        return True;
 }
 
-static BOOL mangle_mask_match(connection_struct *conn, fstring filename, char *mask)
+static BOOL mangle_mask_match(connection_struct *conn, const char *filename,
+               char *mask)
 {
-       mangle_map(filename,True,False,conn->params);
-       return mask_match_search(filename,mask,False);
+       char mname[13];
+
+       if (!name_to_8_3(filename,mname,False,conn->params)) {
+               return False;
+       }
+       return mask_match_search(mname,mask,False);
 }
 
 /****************************************************************************
@@ -807,9 +805,14 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,uint32 dirtype, pstring fn
                    mask_match_search(filename,mask,False) ||
                    mangle_mask_match(conn,filename,mask)) {
 
-                       if (!mangle_is_8_3(filename, False, conn->params))
-                               mangle_map(filename,True,False,
-                                          conn->params);
+                       if (!mangle_is_8_3(filename, False, conn->params)) {
+                               char mname[13];
+                               if (!name_to_8_3(filename,mname,False,
+                                          conn->params)) {
+                                       continue;
+                               }
+                               pstrcpy(filename,mname);
+                       }
 
                        pstrcpy(fname,filename);
                        *path = 0;
@@ -1061,12 +1064,14 @@ BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char *
 struct smb_Dir *OpenDir(connection_struct *conn, const char *name, const char *mask, uint32 attr)
 {
        struct smb_Dir *dirp = SMB_MALLOC_P(struct smb_Dir);
+
        if (!dirp) {
                return NULL;
        }
        ZERO_STRUCTP(dirp);
 
        dirp->conn = conn;
+       dirp->name_cache_size = lp_directory_name_cache_size(SNUM(conn));
 
        dirp->dir_path = SMB_STRDUP(name);
        if (!dirp->dir_path) {
@@ -1078,9 +1083,14 @@ struct smb_Dir *OpenDir(connection_struct *conn, const char *name, const char *m
                goto fail;
        }
 
-       dirp->name_cache = SMB_CALLOC_ARRAY(struct name_cache_entry, NAME_CACHE_SIZE);
-       if (!dirp->name_cache) {
-               goto fail;
+       if (dirp->name_cache_size) {
+               dirp->name_cache = SMB_CALLOC_ARRAY(struct name_cache_entry,
+                               dirp->name_cache_size);
+               if (!dirp->name_cache) {
+                       goto fail;
+               }
+       } else {
+               dirp->name_cache = NULL;
        }
 
        dirhandles_open++;
@@ -1113,7 +1123,7 @@ int CloseDir(struct smb_Dir *dirp)
        }
        SAFE_FREE(dirp->dir_path);
        if (dirp->name_cache) {
-               for (i = 0; i < NAME_CACHE_SIZE; i++) {
+               for (i = 0; i < dirp->name_cache_size; i++) {
                        SAFE_FREE(dirp->name_cache[i].name);
                }
        }
@@ -1229,7 +1239,12 @@ void DirCacheAdd(struct smb_Dir *dirp, const char *name, long offset)
 {
        struct name_cache_entry *e;
 
-       dirp->name_cache_index = (dirp->name_cache_index+1) % NAME_CACHE_SIZE;
+       if (!dirp->name_cache_size || !dirp->name_cache) {
+               return;
+       }
+
+       dirp->name_cache_index = (dirp->name_cache_index+1) %
+                                       dirp->name_cache_size;
        e = &dirp->name_cache[dirp->name_cache_index];
        SAFE_FREE(e->name);
        e->name = SMB_STRDUP(name);
@@ -1248,20 +1263,22 @@ BOOL SearchDir(struct smb_Dir *dirp, const char *name, long *poffset)
        connection_struct *conn = dirp->conn;
 
        /* 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 && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
-                       *poffset = e->offset;
-                       SeekDir(dirp, e->offset);
-                       return True;
+       if (dirp->name_cache_size && dirp->name_cache) {
+               for (i = dirp->name_cache_index; i >= 0; i--) {
+                       struct name_cache_entry *e = &dirp->name_cache[i];
+                       if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
+                               *poffset = e->offset;
+                               SeekDir(dirp, e->offset);
+                               return True;
+                       }
                }
-       }
-       for (i = NAME_CACHE_SIZE-1; i > dirp->name_cache_index; i--) {
-               struct name_cache_entry *e = &dirp->name_cache[i];
-               if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
-                       *poffset = e->offset;
-                       SeekDir(dirp, e->offset);
-                       return True;
+               for (i = dirp->name_cache_size - 1; i > dirp->name_cache_index; i--) {
+                       struct name_cache_entry *e = &dirp->name_cache[i];
+                       if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
+                               *poffset = e->offset;
+                               SeekDir(dirp, e->offset);
+                               return True;
+                       }
                }
        }