shithub: riscv

Download patch

ref: a2abe177e4ec99e3ca22d96fd472c68a19ffe152
parent: 31637404ba902c53ad26a1686e60dd1340000cdb
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Tue Feb 5 15:53:40 EST 2019

cifs: fix pruning of . and .. directory entries (thanks steve simon)

steve wrote:

> I cam across a bug in cifs.
>
> An empty directory under windows 7 pro contains a single entry "." but it
> doesn't appear to contain "..". As a result "." is not removed on dirscan
> and plan9 gets when trying to traverse the hierarchy.

--- a/sys/src/cmd/cifs/main.c
+++ b/sys/src/cmd/cifs/main.c
@@ -189,7 +189,28 @@
 	return smprint("%s/%s", path, name);
 }
 
+/* remove "." and ".." from the cache */
 static int
+rmdots(Aux *a, int got)
+{
+	int i, num;
+	FInfo *fi;
+
+	num = 0;
+	fi = (FInfo *)a->cache;
+	for(i = 0; i < got; i++){
+		if(strcmp(fi->name, ".") == 0 || strcmp(fi->name, "..") == 0){
+			memmove(fi, fi+1, got * sizeof(FInfo));
+			continue;
+		}
+		fi++;
+		num++;
+	}
+
+	return num;
+}
+
+static int
 dirgen(int slot, Dir *d, void *aux)
 {
 	long off;
@@ -200,7 +221,7 @@
 	int numinf = numinfo();
 	int slots;
 
-	slots = 128;		/* number of dir entries to fetch at one time */
+	slots = 32;		/* number of dir entries to fetch at one time */
 
 	if(strcmp(a->path, "/") == 0){
 		if(slot < numinf){
@@ -221,7 +242,6 @@
 		goto from_cache;
 
 	if(off == 0){
-		fi = (FInfo *)a->cache;
 		npath = smprint("%s/*", mapfile(a->path));
 		a->sh = T2findfirst(Sess, a->sp, slots, npath, &got, &a->srch,
 			(FInfo *)a->cache);
@@ -229,15 +249,10 @@
 		if(a->sh == -1)
 			return -1;
 
+		got = rmdots(a, got);
 		a->off = 0;
 		a->end = got * sizeof(FInfo);
-
-		if(got >= 2 && strcmp(fi[0].name, ".") == 0 &&
-		    strcmp(fi[1].name, "..") == 0){
-			a->end = (got - 2) * sizeof(FInfo);
-			memmove(a->cache, a->cache + sizeof(FInfo)*2,
-				a->end - a->off);
-		}
+		goto from_cache;
 	}
 
 	while(off >= a->end && a->sh != -1){
@@ -249,6 +264,7 @@
 		free(npath);
 		if(rc == -1 || got == 0)
 			break;
+		got = rmdots(a, got);
 		a->end = a->off + got * sizeof(FInfo);
 	}
 	a->expire = time(nil) + CACHETIME;
@@ -259,10 +275,11 @@
 		a->sh = -1;
 	}
 
+
+from_cache:
 	if(off >= a->end)
 		return -1;
 
-from_cache:
 	fi = (FInfo *)(a->cache + (off - a->off));
 	npath = smprint("%s/%s", mapfile(a->path), fi->name);
 	I2D(d, a->sp, npath, fi);