summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@gmx.de>2012-11-01 03:42:24 +0100
committercinap_lenrek <cinap_lenrek@gmx.de>2012-11-01 03:42:24 +0100
commit4b2a1c104b35cfdddf54bb8da2a160ba8501f09a (patch)
treeffb1c64be20e555c4c567cb7a5001eaf54e7a51c
parent30d54cc055d1a71edbace68ac29acd048648a259 (diff)
hgfs: strip metadata header, bogus .n walks
-rw-r--r--sys/src/cmd/hgfs/dat.h1
-rw-r--r--sys/src/cmd/hgfs/fns.h1
-rw-r--r--sys/src/cmd/hgfs/fs.c21
-rw-r--r--sys/src/cmd/hgfs/revlog.c28
4 files changed, 48 insertions, 3 deletions
diff --git a/sys/src/cmd/hgfs/dat.h b/sys/src/cmd/hgfs/dat.h
index acab7db5e..17cc05e91 100644
--- a/sys/src/cmd/hgfs/dat.h
+++ b/sys/src/cmd/hgfs/dat.h
@@ -93,6 +93,7 @@ struct Revfile
char *buf;
int fd;
+ int doff; /* length of metadata to skip */
};
uchar nullid[HASHSZ];
diff --git a/sys/src/cmd/hgfs/fns.h b/sys/src/cmd/hgfs/fns.h
index 7e875a6ab..42c6f736f 100644
--- a/sys/src/cmd/hgfs/fns.h
+++ b/sys/src/cmd/hgfs/fns.h
@@ -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);
diff --git a/sys/src/cmd/hgfs/fs.c b/sys/src/cmd/hgfs/fs.c
index 4b58a515c..7f9c37d6a 100644
--- a/sys/src/cmd/hgfs/fs.c
+++ b/sys/src/cmd/hgfs/fs.c
@@ -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;
}
diff --git a/sys/src/cmd/hgfs/revlog.c b/sys/src/cmd/hgfs/revlog.c
index 420a13307..ab4ef1d9f 100644
--- a/sys/src/cmd/hgfs/revlog.c
+++ b/sys/src/cmd/hgfs/revlog.c
@@ -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;
+}