diff --git a/sys/src/cmd/hgfs/dat.h b/sys/src/cmd/hgfs/dat.h index 17cc05e91..70d5ccbc2 100644 --- a/sys/src/cmd/hgfs/dat.h +++ b/sys/src/cmd/hgfs/dat.h @@ -46,6 +46,9 @@ struct Revlog int nmap; Revmap *map; + + int tfd; + int tid; }; struct Revnode diff --git a/sys/src/cmd/hgfs/fns.h b/sys/src/cmd/hgfs/fns.h index 42c6f736f..6145330b0 100644 --- a/sys/src/cmd/hgfs/fns.h +++ b/sys/src/cmd/hgfs/fns.h @@ -6,6 +6,7 @@ int fhash(int fd, uchar p1[], uchar p2[], uchar h[]); int readhash(char *path, char *name, uchar hash[]); /* patch */ +int fcopy(int dfd, int sfd, vlong off, vlong len); int fpatchmark(int pfd, char *mark); int fpatch(int ofd, int bfd, int pfd); diff --git a/sys/src/cmd/hgfs/fs.c b/sys/src/cmd/hgfs/fs.c index 9c61233c3..727cf64d3 100644 --- a/sys/src/cmd/hgfs/fs.c +++ b/sys/src/cmd/hgfs/fs.c @@ -43,6 +43,7 @@ static char *nametab[] = { static Revlog changelog; static Revlog manifest; static Revlog *revlogs; +static int nfreerevlogs = 0; static char workdir[MAXPATH]; static int mangle = 0; @@ -51,16 +52,28 @@ static Revlog* getrevlog(Revnode *nd) { char buf[MAXPATH]; - Revlog *rl; + Revlog *rl, **link; int mang; mang = mangle; Again: nodepath(seprint(buf, buf+sizeof(buf), "%s/.hg/store/data", workdir), buf+sizeof(buf), nd, mang); - for(rl = revlogs; rl; rl = rl->next) - if(strcmp(buf, rl->path) == 0) + link = &revlogs; + while(rl = *link){ + if(strcmp(buf, rl->path) == 0){ + if(rl->ref == 0) nfreerevlogs--; break; + } + if(nfreerevlogs > 8 && rl->ref == 0){ + *link = rl->next; + nfreerevlogs--; + revlogclose(rl); + free(rl); + continue; + } + link = &rl->next; + } if(rl == nil){ rl = emalloc9p(sizeof(*rl)); memset(rl, 0, sizeof(*rl)); @@ -83,18 +96,8 @@ Again: static void closerevlog(Revlog *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); + if(rl != nil && decref(rl) == 0) + nfreerevlogs++; } static Revinfo* diff --git a/sys/src/cmd/hgfs/info.c b/sys/src/cmd/hgfs/info.c index 6a17a8fcc..45877f957 100644 --- a/sys/src/cmd/hgfs/info.c +++ b/sys/src/cmd/hgfs/info.c @@ -8,16 +8,13 @@ Revinfo* loadrevinfo(Revlog *changelog, int rev) { char buf[BUFSZ], *p, *e; - int fd, line, inmsg, n; + int fd, line, eof, inmsg, n; Revinfo *ri; vlong off; if((fd = revlogopentemp(changelog, rev)) < 0) return nil; - seek(fd, 0, 2); - write(fd, "\n", 1); - off = fmetaheader(fd); seek(fd, off, 0); @@ -26,11 +23,19 @@ loadrevinfo(Revlog *changelog, int rev) memmove(ri->chash, changelog->map[rev].hash, HASHSZ); + eof = 0; line = 0; inmsg = 0; p = buf; e = buf + BUFSZ; - while((n = read(fd, p, e - p)) > 0){ + while(eof == 0){ + if((n = read(fd, p, e - p)) < 0) + break; + if(n == 0){ + eof = 1; + *p = '\n'; + n++; + } p += n; while((p > buf) && (e = memchr(buf, '\n', p - buf))){ *e++ = 0; diff --git a/sys/src/cmd/hgfs/patch.c b/sys/src/cmd/hgfs/patch.c index a3d6ef37a..a9d93aa1a 100644 --- a/sys/src/cmd/hgfs/patch.c +++ b/sys/src/cmd/hgfs/patch.c @@ -5,19 +5,25 @@ #include "fns.h" int -fcopy(int dfd, int sfd, vlong len) +fcopy(int dfd, int sfd, vlong off, vlong len) { uchar buf[BUFSZ]; int n; - while(len > 0){ - if((n = BUFSZ) > len) + while(len != 0){ + n = BUFSZ; + if(len > 0 && n > len) n = len; - if((n = read(sfd, buf, n)) < 0) + if((n = pread(sfd, buf, n, off)) < 0) return -1; + if(n == 0) + return len > 0 ? -1 : 0; if(write(dfd, buf, n) != n) return -1; - len -= n; + if(off >= 0) + off += n; + if(len > 0) + len -= n; } return 0; } @@ -58,6 +64,8 @@ fpatch(int ofd, int bfd, int pfd) if(bfd >= 0){ h = malloc(sizeof(Frag)); + if(h == nil) + goto errout; h->next = nil; h->off = 0; h->fd = bfd; @@ -101,6 +109,8 @@ fpatch(int ofd, int bfd, int pfd) back = end < fend; if(front && back){ p = malloc(sizeof(Frag)); + if(p == nil) + goto errout; *p = *f; f->next = p; f->len = start - fstart; @@ -123,6 +133,8 @@ fpatch(int ofd, int bfd, int pfd) fstart += f->len; f = malloc(sizeof(Frag)); + if(f == nil) + goto errout; f->fd = pfd; f->len = len; f->off = seek(f->fd, 0, 1); @@ -141,12 +153,9 @@ fpatch(int ofd, int bfd, int pfd) goto errout; } - for(f = h; f; f = f->next){ - if(seek(f->fd, f->off, 0) < 0) + for(f = h; f; f = f->next) + if(fcopy(ofd, f->fd, f->off, f->len) < 0) goto errout; - if(fcopy(ofd, f->fd, f->len) < 0) - goto errout; - } err = 0; errout: diff --git a/sys/src/cmd/hgfs/revlog.c b/sys/src/cmd/hgfs/revlog.c index ab4ef1d9f..a90363b2e 100644 --- a/sys/src/cmd/hgfs/revlog.c +++ b/sys/src/cmd/hgfs/revlog.c @@ -7,10 +7,10 @@ int fmktemp(void) { - char temp[MAXPATH]; - - snprint(temp, sizeof(temp), "/tmp/hgXXXXXXXXXXX"); - return create(mktemp(temp), OTRUNC|ORCLOSE|ORDWR, 0666); + static ulong id = 1; + char path[MAXPATH]; + snprint(path, sizeof(path), "/tmp/hg%.12d%.8lux", getpid(), id++); + return create(path, OEXCL|OTRUNC|ORDWR|ORCLOSE, 0600); } void @@ -65,6 +65,8 @@ revlogopen(Revlog *r, char *path, int mode) { r->ifd = -1; r->dfd = -1; + r->tfd = -1; + r->tid = -1; path = smprint("%s.i", path); if((r->ifd = open(path, mode)) < 0){ free(path); @@ -94,6 +96,11 @@ revlogclose(Revlog *r) close(r->dfd); r->dfd = -1; } + if(r->tfd >= 0){ + close(r->tfd); + r->tfd = -1; + } + r->tid = -1; free(r->map); r->map = nil; r->nmap = 0; @@ -269,12 +276,19 @@ revlogopentemp(Revlog *r, int rev) { int fd; - if((fd = fmktemp()) < 0) - return -1; - if(revlogextract(r, rev, fd) < 0){ - close(fd); - return -1; + if(r->tfd < 0 || rev != r->tid){ + if((fd = fmktemp()) < 0) + return -1; + if(revlogextract(r, rev, fd) < 0){ + close(fd); + return -1; + } + if(r->tfd >= 0) + close(r->tfd); + r->tfd = fd; + r->tid = rev; } + fd = dup(r->tfd, -1); if(seek(fd, 0, 0) < 0){ close(fd); return -1;