hgfs: strip metadata header, bogus .n walks

This commit is contained in:
cinap_lenrek 2012-11-01 03:42:24 +01:00
parent 30d54cc055
commit 4b2a1c104b
4 changed files with 48 additions and 3 deletions

View file

@ -93,6 +93,7 @@ struct Revfile
char *buf;
int fd;
int doff; /* length of metadata to skip */
};
uchar nullid[HASHSZ];

View file

@ -21,6 +21,7 @@ int revlogextract(Revlog *r, int rev, int ofd);
uchar *revhash(Revlog *r, int rev);
int hashrev(Revlog *r, uchar hash[]);
int revlogopentemp(Revlog *r, int rev);
int fmetaheader(int fd);
/* info */
Revinfo *loadrevinfo(Revlog *changelog, int rev);

View file

@ -298,8 +298,15 @@ fsmkdir(Dir *d, int level, void *aux)
if((rl = getrevlog(nd)) == nil)
break;
if((rev = hashrev(rl, nd->hash)) >= 0){
if(level == Qtree)
if(level == Qtree){
/*
* BUG: this is not correct. mercurial might
* prefix the data log with random \1\n escaped
* metadata strings (see fmetaheader()) and the flen
* *includes* the metadata part. m(
*/
d->length = rl->map[rev].flen;
}
ri = getrevinfo(rl->map[rev].linkrev);
}
closerevlog(rl);
@ -490,7 +497,13 @@ fswalk1(Fid *fid, char *name, Qid *qid)
sname += 3;
}
snprint(buf, sizeof(buf), "%.*s", i, name);
i = atoi(sname);
if(*sname == 0)
i = 0;
else {
i = strtol(sname, &sname, 10);
if(i < 0 || *sname != '\0')
goto Notfound;
}
sname = buf;
goto Searchtree;
}
@ -680,6 +693,7 @@ fsread(Req *r)
responderror(r);
return;
}
rf->doff = fmetaheader(rf->fd);
goto Fdgen;
case Qwho:
s = rf->info->who;
@ -706,8 +720,9 @@ fsread(Req *r)
responderror(r);
return;
}
rf->doff = fmetaheader(rf->fd);
Fdgen:
if((n = pread(rf->fd, r->ofcall.data, len, off)) < 0){
if((n = pread(rf->fd, r->ofcall.data, len, off + rf->doff)) < 0){
responderror(r);
return;
}

View file

@ -281,3 +281,31 @@ revlogopentemp(Revlog *r, int rev)
}
return fd;
}
int
fmetaheader(int fd)
{
static char magic[2] = { 0x01, 0x0A, };
char buf[4096], *s, *p;
int o, n;
o = 0;
while(o < sizeof(buf)){
if((n = pread(fd, buf+o, sizeof(buf)-o, o)) <= 0)
break;
o += n;
if(o < sizeof(magic))
continue;
if(memcmp(buf, magic, sizeof(magic)) != 0)
break;
s = buf + sizeof(magic);
while((s - buf) <= (o - sizeof(magic))){
if((p = memchr(s, magic[0], o - (s - buf))) == nil)
break;
if(memcmp(p, magic, sizeof(magic)) == 0)
return (p - buf) + sizeof(magic);
s = p+1;
}
}
return 0;
}