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){