hgfs: fix path mangeling bug, find dothg on startup

This commit is contained in:
cinap_lenrek 2011-06-30 03:05:10 +02:00
parent 2f1a0685ea
commit 62186910fa
4 changed files with 94 additions and 51 deletions

View file

@ -35,6 +35,8 @@ struct Revlog
{
Ref;
Revlog *next;
char *path;
int ifd;
@ -67,7 +69,7 @@ struct Revinfo
char *who;
char *why;
long when;
ulong when;
vlong logoff;
vlong loglen;

View file

@ -40,20 +40,31 @@ static char *nametab[] = {
static Revlog changelog;
static Revlog manifest;
static Revlog *revlogs;
static char dothg[MAXPATH];
static Revlog*
getrevlog(Revnode *nd)
{
char path[MAXPATH];
char buf[MAXPATH];
Revlog *rl;
nodepath(seprint(path, path+MAXPATH, ".hg/store/data"), path+MAXPATH, nd);
rl = emalloc9p(sizeof(*rl));
memset(rl, 0, sizeof(*rl));
if(revlogopen(rl, path, OREAD) < 0){
free(rl);
return nil;
}
nodepath(seprint(buf, buf+sizeof(buf), "%s/store/data", dothg), buf+sizeof(buf), nd);
for(rl = revlogs; rl; rl = rl->next)
if(strcmp(buf, rl->path) == 0)
break;
if(rl == nil){
rl = emalloc9p(sizeof(*rl));
memset(rl, 0, sizeof(*rl));
if(revlogopen(rl, buf, OREAD) < 0){
free(rl);
return nil;
}
rl->next = revlogs;
revlogs = rl;
} else
revlogupdate(rl);
incref(rl);
return rl;
}
@ -61,10 +72,16 @@ getrevlog(Revnode *nd)
static void
closerevlog(Revlog *rl)
{
if(rl == nil)
return;
if(decref(rl))
Revlog **pp;
if(rl == nil || decref(rl))
return;
for(pp = &revlogs; *pp; pp = &((*pp)->next)){
if(*pp == rl){
*pp = rl->next;
break;
}
}
revlogclose(rl);
free(rl);
}
@ -189,6 +206,15 @@ fsmkqid(Qid *q, int level, void *aux)
}
}
static char*
fsmkrevname(char *buf, int nbuf, int rev)
{
if(rev < 0 || rev >= changelog.nmap)
return nil;
snprint(buf, nbuf, "%d.%H", rev, changelog.map[rev].hash);
return buf;
}
static void
fsmkdir(Dir *d, int level, void *aux)
{
@ -205,7 +231,6 @@ fsmkdir(Dir *d, int level, void *aux)
if(d->qid.type == QTDIR)
d->mode |= DMDIR | 0111;
s = nil;
ri = nil;
switch(level){
case Qroot:
@ -220,10 +245,9 @@ fsmkdir(Dir *d, int level, void *aux)
rev = changelog.map[rev].p1rev;
else if(level == Qrev2)
rev = changelog.map[rev].p2rev;
if(rev >= 0)
snprint(s = buf, sizeof(buf), "%d.%H", rev, changelog.map[rev].hash);
s = fsmkrevname(buf, sizeof(buf), rev);
if(level == Qrev){
d->name = estrdup9p(buf);
d->name = estrdup9p(s);
break;
}
goto Strgen;
@ -252,9 +276,9 @@ fsmkdir(Dir *d, int level, void *aux)
case Qtree:
case Qtreerev:
nd = aux;
d->name = estrdup9p(nd->name);
if(nd->mode == 'x')
if(level == Qtree && nd->mode == 'x')
d->mode |= 0111;
d->name = estrdup9p(nd->name);
if(nd->hash){
Revlog *rl;
@ -363,10 +387,9 @@ static char*
fswalk1(Fid *fid, char *name, Qid *qid)
{
Revtree* (*loadfn)(Revlog *, Revlog *, Revinfo *);
char path[MAXPATH];
char buf[MAXPATH], *sname;
Revnode *nd;
Revfile *rf;
char *sname;
int i, level;
if(!(fid->qid.type&QTDIR))
@ -453,9 +476,9 @@ fswalk1(Fid *fid, char *name, Qid *qid)
level = Qtreerev;
sname += 3;
}
snprint(path, sizeof(path), "%.*s", i, name);
snprint(buf, sizeof(buf), "%.*s", i, name);
i = atoi(sname);
sname = path;
sname = buf;
goto Searchtree;
}
}
@ -483,7 +506,7 @@ fswalk1(Fid *fid, char *name, Qid *qid)
nd->before = nb;
}
nd = nb;
} else if(i || level != Qtree)
} else if(name != sname)
goto Notfound;
rf->node = nd;
rf->level = level;
@ -593,9 +616,8 @@ treegen(int i, Dir *d, void *aux)
static void
fsread(Req *r)
{
char buf[MAXPATH], *s;
Revfile *rf;
char buf[MAXPATH];
char *s;
int i, n;
vlong off;
int len;
@ -620,18 +642,15 @@ fsread(Req *r)
s = nil;
if(rf->buf)
goto Strgen;
if((i = hashrev(&changelog, rf->info->chash)) >= 0){
if(rf->level == Qrev1)
i = changelog.map[i].p1rev;
else
i = changelog.map[i].p2rev;
i = hashrev(&changelog, rf->info->chash);
if(rf->level == Qrev1)
i = changelog.map[i].p1rev;
else
i = changelog.map[i].p2rev;
Revgen:
if(i >= 0)
snprint(s = buf, sizeof(buf), "%d.%H", i, changelog.map[i].hash);
}
s = fsmkrevname(buf, sizeof(buf), i);
goto Strgen;
case Qtreerev:
s = nil;
if((i = hashrev(rf->rlog, rf->node->hash)) >= 0)
i = rf->rlog->map[i].linkrev;
goto Revgen;
@ -699,7 +718,7 @@ Srv fs =
void
usage(void)
{
fprint(2, "usage: %s [-D] [-m mtpt] [-s srv]\n", argv0);
fprint(2, "usage: %s [-D] [-m mtpt] [-s srv] [root]\n", argv0);
exits("usage");
}
@ -707,6 +726,7 @@ void
main(int argc, char *argv[])
{
char *srv, *mtpt;
char buf[MAXPATH];
inflateinit();
fmtinstall('H', Hfmt);
@ -728,9 +748,29 @@ main(int argc, char *argv[])
usage();
} ARGEND;
if(revlogopen(&changelog, ".hg/store/00changelog", OREAD) < 0)
if(*argv){
snprint(dothg, sizeof(dothg), "%s/.hg", *argv);
}else{
if(getwd(buf, sizeof(buf)) == nil)
sysfatal("can't get working dir: %r");
for(;;){
char *s;
snprint(dothg, sizeof(dothg), "%s/.hg", buf);
if(access(dothg, AEXIST) == 0)
break;
if((s = strrchr(buf, '/')) == nil)
break;
*s = 0;
}
}
cleanname(dothg);
snprint(buf, sizeof(buf), "%s/store/00changelog", dothg);
if(revlogopen(&changelog, buf, OREAD) < 0)
sysfatal("can't open changelog: %r\n");
if(revlogopen(&manifest, ".hg/store/00manifest", OREAD) < 0)
snprint(buf, sizeof(buf), "%s/store/00manifest", dothg);
if(revlogopen(&manifest, buf, OREAD) < 0)
sysfatal("can't open menifest: %r\n");
postmountsrv(&fs, srv, mtpt, MREPL);

View file

@ -18,6 +18,7 @@ revlogupdate(Revlog *r)
{
uchar buf[64];
Revmap *m;
vlong noff;
int rev;
if(seek(r->ifd, r->ioff, 0) < 0)
@ -47,11 +48,14 @@ revlogupdate(Revlog *r)
m->p2rev = buf[28]<<24 | buf[29]<<16 | buf[30]<<8 | buf[31];
memmove(m->hash, buf+32, HASHSZ);
noff = r->ioff + sizeof(buf);
if(r->dfd < 0){
m->hoff = seek(r->ifd, 0, 1);
r->ioff = seek(r->ifd, m->hlen, 1);
} else
r->ioff = seek(r->ifd, 0, 1);
m->hoff = noff;
noff = seek(r->ifd, m->hoff + m->hlen, 0);
if(noff < 0)
break;
}
r->ioff = noff;
}
r->nmap = rev;
}

View file

@ -13,7 +13,7 @@ nodepath(char *s, char *e, Revnode *nd)
"lpt1", "lpt2", "lpt3", "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9",
};
char *p;
int i;
int i, l;
if(nd == nil || nd->name == nil)
return s;
@ -21,10 +21,11 @@ nodepath(char *s, char *e, Revnode *nd)
s = seprint(nodepath(s, e, nd->up), e, "/");
p = nd->name;
for(i=0; i<nelem(frogs); i++)
if(strncmp(frogs[i], p, strlen(frogs[i])) == 0)
for(i=0; i<nelem(frogs); i++){
l = strlen(frogs[i]);
if((strncmp(frogs[i], p, l) == 0) && (p[l] == 0 || p[l] == '.'))
return seprint(s, e, "%.2s~%.2x%s", p, p[2], p+3);
}
for(; s+4 < e && *p; p++){
if(*p == '_'){
*s++ = '_';
@ -50,20 +51,16 @@ mknode(char *name, uchar *hash, char mode)
char *s;
d = malloc(sizeof(*d) + (hash ? HASHSZ : 0) + (name ? strlen(name)+1 : 0));
d->up = d->down = d->next = d->before = nil;
memset(d, 0, sizeof(*d));
s = (char*)&d[1];
if(hash){
d->path = *((uvlong*)hash);
memmove(d->hash = (uchar*)s, hash, HASHSZ);
s += HASHSZ;
} else {
}else
d->path = 1;
d->hash = nil;
}
if(name)
strcpy(d->name = s, name);
else
d->name = nil;
d->mode = mode;
return d;
}