first two entries in a directory. This is what caused the FC3 system
shelob in the build farm to fail the RAW-UNLINK and RAW-SEARCH tests.
(This used to be commit
f48abaaaca301c025ebd381f62345b3869809917)
uint32_t name_cache_index;
};
uint32_t name_cache_index;
};
+#define DIR_OFFSET_DOT 0
+#define DIR_OFFSET_DOTDOT 1
+#define DIR_OFFSET_BASE 2
+
+
/*
a special directory listing case where the pattern has no wildcard. We can just do a single stat()
thus avoiding the more expensive directory scan
/*
a special directory listing case where the pattern has no wildcard. We can just do a single stat()
thus avoiding the more expensive directory scan
+/*
+ add an entry to the local cache
+*/
+static void dcache_add(struct pvfs_dir *dir, const char *name)
+{
+ struct name_cache_entry *e;
+
+ dir->name_cache_index = (dir->name_cache_index+1) % NAME_CACHE_SIZE;
+ e = &dir->name_cache[dir->name_cache_index];
+
+ if (e->name) talloc_free(e->name);
+
+ e->name = talloc_strdup(dir->name_cache, name);
+ e->offset = dir->offset;
+}
+
/*
return the next entry
*/
const char *pvfs_list_next(struct pvfs_dir *dir, uint_t *ofs)
{
struct dirent *de;
/*
return the next entry
*/
const char *pvfs_list_next(struct pvfs_dir *dir, uint_t *ofs)
{
struct dirent *de;
+ enum protocol_types protocol = dir->pvfs->tcon->smb_conn->negotiate.protocol;
/* non-wildcard searches are easy */
if (dir->no_wildcard) {
/* non-wildcard searches are easy */
if (dir->no_wildcard) {
return dir->single_name;
}
return dir->single_name;
}
- if (*ofs != dir->offset) {
- seekdir(dir->dir, *ofs);
+ /* . and .. are handled separately as some unix systems will
+ not return them first in a directory, but windows client
+ may assume that these entries always appear first */
+ if (*ofs == DIR_OFFSET_DOT) {
+ (*ofs)++;
+ if (ms_fnmatch(dir->pattern, ".", protocol) == 0) {
+ dcache_add(dir, ".");
+ return ".";
+ }
+
+ if (*ofs == DIR_OFFSET_DOTDOT) {
+ (*ofs)++;
+ dir->offset = *ofs;
+ if (ms_fnmatch(dir->pattern, "..", protocol) == 0) {
+ dcache_add(dir, "..");
+ return "..";
+ }
+ }
+
+ if (*ofs == DIR_OFFSET_BASE) {
+ rewinddir(dir->dir);
+ } else if (*ofs != dir->offset) {
+ seekdir(dir->dir, (*ofs) - DIR_OFFSET_BASE);
+ }
+ dir->offset = *ofs;
while ((de = readdir(dir->dir))) {
const char *dname = de->d_name;
while ((de = readdir(dir->dir))) {
const char *dname = de->d_name;
- struct name_cache_entry *e;
- if (ms_fnmatch(dir->pattern, dname,
- dir->pvfs->tcon->smb_conn->negotiate.protocol) != 0) {
+ if (strcmp(dname, ".") == 0 ||
+ strcmp(dname, "..") == 0) {
+ continue;
+ }
+
+ if (ms_fnmatch(dir->pattern, dname, protocol) != 0) {
char *short_name = pvfs_short_name_component(dir->pvfs, dname);
if (short_name == NULL ||
char *short_name = pvfs_short_name_component(dir->pvfs, dname);
if (short_name == NULL ||
- ms_fnmatch(dir->pattern, short_name,
- dir->pvfs->tcon->smb_conn->negotiate.protocol) != 0) {
+ ms_fnmatch(dir->pattern, short_name, protocol) != 0) {
talloc_free(short_name);
continue;
}
talloc_free(short_name);
}
talloc_free(short_name);
continue;
}
talloc_free(short_name);
}
- dir->offset = telldir(dir->dir);
+ dir->offset = telldir(dir->dir) + DIR_OFFSET_BASE;
- dir->name_cache_index = (dir->name_cache_index+1) % NAME_CACHE_SIZE;
- e = &dir->name_cache[dir->name_cache_index];
+ dcache_add(dir, dname);
- if (e->name) talloc_free(e->name);
-
- e->name = talloc_strdup(dir->name_cache, de->d_name);
- e->offset = dir->offset;
-
- return e->name;
}
dir->end_of_search = True;
}
dir->end_of_search = True;
struct dirent *de;
int i;
struct dirent *de;
int i;
+ if (strcmp(name, ".") == 0) {
+ dir->offset = DIR_OFFSET_DOTDOT;
+ *ofs = dir->offset;
+ return NT_STATUS_OK;
+ }
+
+ if (strcmp(name, "..") == 0) {
+ dir->offset = DIR_OFFSET_BASE;
+ *ofs = dir->offset;
+ return NT_STATUS_OK;
+ }
+
for (i=dir->name_cache_index;i>=0;i--) {
struct name_cache_entry *e = &dir->name_cache[i];
if (e->name && StrCaseCmp(name, e->name) == 0) {
for (i=dir->name_cache_index;i>=0;i--) {
struct name_cache_entry *e = &dir->name_cache[i];
if (e->name && StrCaseCmp(name, e->name) == 0) {
while ((de = readdir(dir->dir))) {
if (StrCaseCmp(name, de->d_name) == 0) {
while ((de = readdir(dir->dir))) {
if (StrCaseCmp(name, de->d_name) == 0) {
- dir->offset = telldir(dir->dir);
+ dir->offset = telldir(dir->dir) + DIR_OFFSET_BASE;
*ofs = dir->offset;
return NT_STATUS_OK;
}
*ofs = dir->offset;
return NT_STATUS_OK;
}