--- dir.c.original 2004-09-23 11:24:56.132481124 -0700 +++ dir.c 2004-09-16 15:49:24.000000000 -0700 @@ -219,6 +219,8 @@ struct directory_contents *next; dev_t dev; /* Device and inode numbers of this dir. */ + int mtime; /* controls check for stale directory cache */ + char *path_key; #ifdef WINDOWS32 /* * Inode means nothing on WINDOWS32. Even file key information is @@ -228,8 +230,6 @@ * though, this is also unreliable. I'm open to suggestion on a better * way to emulate inode. */ - char *path_key; - int mtime; /* controls check for stale directory cache */ int fs_flags; /* FS_FAT, FS_NTFS, ... */ #define FS_FAT 0x1 #define FS_NTFS 0x2 @@ -406,9 +406,9 @@ /* Enter it in the contents hash table. */ dc->dev = st.st_dev; + dc->mtime = st.st_mtime; #ifdef WINDOWS32 dc->path_key = xstrdup(w32_path); - dc->mtime = st.st_mtime; /* * NTFS is the only WINDOWS32 filesystem that bumps mtime @@ -428,6 +428,7 @@ else dc->fs_flags = FS_UNKNOWN; #else + dc->path_key = xstrdup(name); # ifdef VMS dc->ino[0] = st.st_ino[0]; dc->ino[1] = st.st_ino[1]; @@ -481,10 +482,8 @@ register char *p; register struct dirfile *df; register struct dirent *d; -#ifdef WINDOWS32 struct stat st; int rehash = 0; -#endif if (dir == 0 || dir->files == 0) { @@ -530,9 +529,9 @@ /* The file was not found in the hashed list. Try to read the directory further. */ +#ifdef WINDOWS32 if (dir->dirstream == 0) { -#ifdef WINDOWS32 /* * Check to see if directory has changed since last read. FAT * filesystems force a rehash always as mtime does not change @@ -554,76 +553,92 @@ else return 0; /* couldn't re-read - fail */ } else -#endif - /* The directory has been all read in. */ - return 0; } +#endif - while ((d = readdir (dir->dirstream)) != 0) + do { - /* Enter the file in the hash table. */ - register unsigned int newhash = 0; - unsigned int len; - register unsigned int i; + if (dir->dirstream != 0) + { + while ((d = readdir (dir->dirstream)) != 0) + { + /* Enter the file in the hash table. */ + register unsigned int newhash = 0; + unsigned int len; + register unsigned int i; #if defined(VMS) && defined(HAVE_DIRENT_H) - /* In VMS we get file versions too, which have to be stripped off */ - { - char *p = strrchr (d->d_name, ';'); - if (p) - *p = '\0'; - } + /* In VMS we get file versions too, which have to be stripped off */ + { + char *p = strrchr (d->d_name, ';'); + if (p) + *p = '\0'; + } #endif - if (!REAL_DIR_ENTRY (d)) - continue; + if (!REAL_DIR_ENTRY (d)) + continue; - len = NAMLEN (d); - for (i = 0; i < len; ++i) - HASHI (newhash, d->d_name[i]); - newhash %= DIRFILE_BUCKETS; -#ifdef WINDOWS32 - /* - * If re-reading a directory, check that this file isn't already - * in the cache. - */ - if (rehash) { - for (df = dir->files[newhash]; df != 0; df = df->next) - if (streq(df->name, d->d_name)) - break; - } else - df = 0; + len = NAMLEN (d); + for (i = 0; i < len; ++i) + HASHI (newhash, d->d_name[i]); + newhash %= DIRFILE_BUCKETS; + + /* + * If re-reading a directory, check that this file isn't already + * in the cache. + */ + if (rehash) { + for (df = dir->files[newhash]; df != 0; df = df->next) + if (streq(df->name, d->d_name)) + break; + } else + df = 0; + + /* + * If re-reading a directory, don't cache files that have + * already been discovered. + */ + if (!df) { + df = (struct dirfile *) xmalloc (sizeof (struct dirfile)); + df->next = dir->files[newhash]; + dir->files[newhash] = df; + df->name = savestring (d->d_name, len); + df->impossible = 0; + } - /* - * If re-reading a directory, don't cache files that have - * already been discovered. - */ - if (!df) { -#endif + /* Check if the name matches the one we're searching for. */ + if (filename != 0 + && newhash == hash && strieq (d->d_name, filename)) + { + return 1; + } + } - df = (struct dirfile *) xmalloc (sizeof (struct dirfile)); - df->next = dir->files[newhash]; - dir->files[newhash] = df; - df->name = savestring (d->d_name, len); - df->impossible = 0; -#ifdef WINDOWS32 + /* If the directory has been completely read in, + close the stream and reset the pointer to nil. */ + if (d == 0) + { + --open_directories; + closedir (dir->dirstream); + dir->dirstream = 0; + } } -#endif - /* Check if the name matches the one we're searching for. */ - if (filename != 0 - && newhash == hash && strieq (d->d_name, filename)) - { - return 1; - } - } - /* If the directory has been completely read in, - close the stream and reset the pointer to nil. */ - if (d == 0) - { - --open_directories; - closedir (dir->dirstream); - dir->dirstream = 0; - } + if (dir->path_key && + (stat(dir->path_key, &st) == 0 && + st.st_mtime > dir->mtime)) + { + /* reset date stamp to show most recent re-process */ + dir->mtime = st.st_mtime; + + /* make sure directory can still be opened */ + dir->dirstream = opendir(dir->path_key); + + if (dir->dirstream) + rehash = 1; + } + } while (dir->dirstream != NULL); + return 0; }