svn commit: samba r8753 - in branches/SAMBA_4_0/source/ntvfs/posix: .

tridge at samba.org tridge at samba.org
Mon Jul 25 10:40:18 GMT 2005


Author: tridge
Date: 2005-07-25 10:40:17 +0000 (Mon, 25 Jul 2005)
New Revision: 8753

WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=8753

Log:
fixed directory handling on systems that do not return . and .. as the
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.

Modified:
   branches/SAMBA_4_0/source/ntvfs/posix/pvfs_dirlist.c


Changeset:
Modified: branches/SAMBA_4_0/source/ntvfs/posix/pvfs_dirlist.c
===================================================================
--- branches/SAMBA_4_0/source/ntvfs/posix/pvfs_dirlist.c	2005-07-25 06:33:51 UTC (rev 8752)
+++ branches/SAMBA_4_0/source/ntvfs/posix/pvfs_dirlist.c	2005-07-25 10:40:17 UTC (rev 8753)
@@ -45,6 +45,11 @@
 	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
@@ -150,12 +155,29 @@
 	return NT_STATUS_OK;
 }
 
+/*
+  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;
+	enum protocol_types protocol = dir->pvfs->tcon->smb_conn->negotiate.protocol;
 
 	/* non-wildcard searches are easy */
 	if (dir->no_wildcard) {
@@ -165,39 +187,58 @@
 		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)++;
 		dir->offset = *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;
-		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 ||
-			    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);
 		}
 
-		dir->offset = telldir(dir->dir);
+		dir->offset = telldir(dir->dir) + DIR_OFFSET_BASE;
 		(*ofs) = dir->offset;
 
-		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;
+		return dname;
 	}
 
 	dir->end_of_search = True;
@@ -228,6 +269,18 @@
 	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) {
@@ -247,7 +300,7 @@
 
 	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;
 		}



More information about the samba-cvs mailing list