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

This commit is contained in:
aiju 2017-04-28 20:42:38 +00:00
parent 7cc9d944df
commit f00488ec70

View file

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