ref: 7722220ff5673036f3d058ebfdd45fe3078057da
parent: e09c2b721b7d4f0d0750c3338dd227d4bc3a95c5
author: cinap_lenrek <[email protected]>
date: Fri Sep 22 07:48:41 EDT 2017
sshfs: use mtime for qid.vers, fix wstat without name change, fix wstat memory leak
--- a/sys/src/cmd/sshfs.c
+++ b/sys/src/cmd/sshfs.c
@@ -468,7 +468,7 @@
}
void
-walkprocess(Req *r, int isdir, char *e)
+walkprocess(Req *r, char *e)
{
char *p;
SFid *sf;
@@ -486,8 +486,6 @@
submitreq(r);
}else{
assert(r->ofcall.nwqid > 0);
- if(!isdir)
- r->ofcall.wqid[r->ofcall.nwqid - 1].type = 0;
wlock(sf);
free(sf->fn);
sf->fn = r->aux;
@@ -529,6 +527,7 @@
d->qid.type = d->mode >> 24;
if((flags & SSH_FILEXFER_ATTR_ACMODTIME) != 0){
rc = unpack(p, ep - p, "uu", &d->atime, &d->mtime); if(rc < 0) return -1; p += rc;
+ d->qid.vers = d->mtime;
}
if((flags & SSH_FILEXFER_ATTR_EXTENDED) != 0){
rc = unpack(p, ep - p, "u", &next); if(rc < 0) return -1; p += rc;
@@ -547,7 +546,7 @@
uchar *r, *p, *e;
u32int fl;
int uid, gid;
-
+
werrstr("phase error");
r = emalloc9p(MAXATTRIB);
e = r + MAXATTRIB;
@@ -589,21 +588,26 @@
}
int
-attribisdir(char *fn)
+attrfixupqid(Qid *qid)
{
- u32int code;
+ u32int flags;
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;
- }
+
+ if(unpack(rxpkt, rxlen, "_____u", &flags) < 0) 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;
+ if(flags & SSH_FILEXFER_ATTR_SIZE) p += 8;
+ if(flags & SSH_FILEXFER_ATTR_UIDGID) p += 8;
+ if(flags & SSH_FILEXFER_ATTR_PERMISSIONS){
+ if(p + 4 > rxpkt + rxlen) return -1;
+ if((GET4(p) & 0170000) != 0040000) qid->type = 0;
+ p += 4;
+ }
+ if(flags & SSH_FILEXFER_ATTR_ACMODTIME){
+ if(p + 8 > rxpkt + rxlen) return -1;
+ p += 4;
+ qid->vers = GET4(p); /* mtime for qid.vers */
+ }
+ return 0;
}
int
@@ -903,6 +907,7 @@
else
sendpkt("bus[", SSH_FXP_SETSTAT, r->reqid, sf->fn, strlen(sf->fn), s, x);
runlock(sf);
+ free(s);
break;
case Tremove:
rlock(sf);
@@ -927,7 +932,7 @@
SReq *r;
SFid *sf;
- int t, id, rc;
+ int t, id;
u32int code;
char *msg, *lang, *hand;
int msgn, langn, handn;
@@ -978,11 +983,10 @@
switch(r->req->ifcall.type){
case Tattach:
if(t != SSH_FXP_ATTRS) goto common;
- rc = attribisdir(r->req->ifcall.aname);
- r->req->aux = (void*)-1;
- if(rc < 0)
+ if(attrfixupqid(&r->req->ofcall.qid) < 0)
goto garbage;
- if(rc == 0)
+ r->req->aux = (void*)-1;
+ if((r->req->ofcall.qid.type & QTDIR) == 0)
respond(r->req, "not a directory");
else
sshfsattach(r->req);
@@ -989,9 +993,10 @@
break;
case Twalk:
if(t != SSH_FXP_ATTRS) goto common;
- rc = attribisdir(((SFid*)r->req->fid)->fn);
- if(rc < 0) goto garbage;
- walkprocess(r->req, rc, nil);
+ if(r->req->ofcall.nwqid <= 0
+ || attrfixupqid(&r->req->ofcall.wqid[r->req->ofcall.nwqid - 1]) < 0)
+ goto garbage;
+ walkprocess(r->req, nil);
break;
case Tcreate:
if(okresp && r->req->aux == (void*)-1){
@@ -1056,6 +1061,10 @@
break;
case Twstat:
if(!okresp) goto common;
+ if(!r->req->d.name[0]){
+ respond(r->req, nil);
+ break;
+ }
if(r->req->aux == nil){
r->req->aux = (void *) -1;
submitreq(r->req);
@@ -1111,7 +1120,7 @@
fprint(2, "sshfs: received unexpected packet %Σ for 9p request %F\n", t, &r->req->ifcall);
}
if(r->req->ifcall.type == Twalk)
- walkprocess(r->req, 0, e);
+ walkprocess(r->req, e);
else
respond(r->req, e);
putsreq(r);