shithub: riscv

Download patch

ref: f00488ec70c0ca00396d3d3e47b38285599dd31a
parent: 7cc9d944df78deb70230b74285287ef429ca14c1
author: aiju <devnull@localhost>
date: Fri Apr 28 16:42:38 EDT 2017

sshfs: check correctly for directory bits; calculate parent directory correctly

--- a/sys/src/cmd/sshfs.c
+++ b/sys/src/cmd/sshfs.c
@@ -450,6 +450,7 @@
 	q = strdup(p);
 	r = strrchr(q, '/');
 	if(r != nil) *r = 0;
+	else strcpy(q, ".");
 	return q;
 }
 
@@ -529,7 +530,7 @@
 	if((flags & SSH_FILEXFER_ATTR_PERMISSIONS) != 0){
 		rc = unpack(p, ep - p, "u", &perm); if(rc < 0) return -1; p += rc;
 		d->mode = perm & 0777;
-		if((perm & 0040000) != 0) d->mode |= DMDIR;
+		if((perm & 0170000) == 0040000) d->mode |= DMDIR;
 	}
 	d->qid.type = d->mode >> 24;
 	if((flags & SSH_FILEXFER_ATTR_ACMODTIME) != 0){
@@ -594,6 +595,24 @@
 }
 
 int
+attribisdir(char *fn)
+{
+	u32int code;
+	uchar *p;
+	
+	if(unpack(rxpkt, rxlen, "_____u", &code) < 0) return -1;
+	if((code & 4) == 0){
+		fprint(2, "sshfs: can't determine if %s is a directory\n", fn);
+		return 1;
+	}
+	p = rxpkt + 9;
+	if(code & 1) p += 8;
+	if(code & 2) p += 8;
+	if(p + 4 > rxpkt + rxlen) return -1;
+	return (GET4(p) & 0170000) == 0040000;
+}
+
+int
 parsedir(SFid *sf)
 {
 	int i, rc;
@@ -860,7 +879,7 @@
 			rlock(sf);
 			r->req->d.name = finalelem(sf->fn);
 			r->req->d.qid = sf->qid;
-			if(sf->handn > 0)
+			if(sf->handn > 0 && (sf->qid.type & QTDIR) == 0)
 				sendpkt("bus", SSH_FXP_FSTAT, r->reqid, sf->hand, sf->handn);
 			else
 				sendpkt("bus", SSH_FXP_STAT, r->reqid, sf->fn, strlen(sf->fn));
@@ -913,12 +932,11 @@
 
 	SReq *r;
 	SFid *sf;
-	int t, id;
+	int t, id, rc;
 	u32int code;
 	char *msg, *lang, *hand;
 	int msgn, langn, handn;
 	int okresp;
-	uchar *p;
 	char *e;
 	
 	threadsetname("recv");
@@ -965,18 +983,11 @@
 		switch(r->req->ifcall.type){
 		case Tattach:
 			if(t != SSH_FXP_ATTRS) goto common;
-			if(unpack(rxpkt, rxlen, "_____u", &code) < 0) goto garbage;
+			rc = attribisdir(r->req->ifcall.aname);
 			r->req->aux = (void*)-1;
-			if((code & 4) == 0){
-				fprint(2, "sshfs: can't determine if %s is a directory\n", r->req->ifcall.aname);
-				sshfsattach(r->req);
-				break;
-			}
-			p = rxpkt + 9;
-			if(code & 1) p += 8;
-			if(code & 2) p += 8;
-			if(p + 4 > rxpkt + rxlen) goto garbage;
-			if((GET4(p) & 0040000) == 0)
+			if(rc < 0)
+				goto garbage;
+			if(rc == 0)
 				respond(r->req, "not a directory");
 			else
 				sshfsattach(r->req);
@@ -983,17 +994,9 @@
 			break;
 		case Twalk:
 			if(t != SSH_FXP_ATTRS) goto common;
-			if(unpack(rxpkt, rxlen, "_____u", &code) < 0) goto garbage;
-			if((code & 4) == 0){
-				fprint(2, "sshfs: can't determine if %s is a directory\n", ((SFid*)r->req->fid)->fn);
-				walkprocess(r->req, 0, nil);
-				break;
-			}
-			p = rxpkt + 9;
-			if(code & 1) p += 8;
-			if(code & 2) p += 8;
-			if(p + 4 > rxpkt + rxlen) goto garbage;
-			walkprocess(r->req, GET4(p) & 0040000, nil);
+			rc = attribisdir(((SFid*)r->req->fid)->fn);
+			if(rc < 0) goto garbage;
+			walkprocess(r->req, rc, nil);
 			break;
 		case Tcreate:
 			if(okresp && r->req->aux == (void*)-1){