ref: e8242918f4073dfff640da6b4a01287664ccb9f0
parent: 970d3b7eb7dc56aa84924dd68c4c39fd1df5d1f5
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sat Nov 25 14:04:01 EST 2023
ndb/mkhash: handle database= reordering, check offset overflow, remove file when opening /lib/ndb/local, the db returned is the first entry in the database= tuple, not the file passed to ndbopen(), so search for the file in question. make sure the file-offset doesnt exceed the NDBSPEC bit (23-bit). remove the created hash file on error, and set TMP bit.
--- a/sys/src/cmd/ndb/mkhash.c
+++ b/sys/src/cmd/ndb/mkhash.c
@@ -11,16 +11,8 @@
ulong hlen;
Ndb *db;
ulong nextchain;
+char err[ERRMAX];
-char*
-syserr(void)
-{
- static char buf[ERRMAX];
-
- errstr(buf, sizeof buf);
- return buf;
-}
-
void
enter(char *val, ulong dboff)
{
@@ -28,6 +20,8 @@
uchar *last;
ulong ptr;
+ assert(dboff < NDBSPEC);
+
h = ndbhash(val, hlen);
h *= NDBPLEN;
last = &ht[h];
@@ -37,6 +31,8 @@
return;
}
+ assert(nextchain < NDBSPEC);
+
if(ptr & NDBCHAIN){
/* walk the chain to the last entry */
for(;;){
@@ -61,16 +57,14 @@
nextchain += 2*NDBPLEN;
}
-uchar nbuf[16*1024];
-
void
main(int argc, char **argv)
{
Ndbtuple *t, *nt;
int n;
- Dir *d;
- uchar buf[8];
- char file[128];
+ Dir *d;
+ uchar buf[NDBHLEN];
+ char *file;
int fd;
ulong off;
uchar *p;
@@ -80,14 +74,14 @@
exits("usage");
}
db = ndbopen(argv[1]);
- if(db == 0){
+ while(db != nil && strcmp(db->file, argv[1]) != 0)
+ db = db->next;
+ if(db == nil){
+ errstr(err, sizeof(err));
fprint(2, "mkhash: can't open %s\n", argv[1]);
- exits(syserr());
+ exits(err);
}
- /* try a bigger than normal buffer */
- Binits(&db->b, Bfildes(&db->b), OREAD, nbuf, sizeof(nbuf));
-
/* count entries to calculate hash size */
n = 0;
@@ -99,13 +93,18 @@
ndbfree(nt);
}
+ if(Boffset(&db->b) >= NDBSPEC){
+ fprint(2, "mkhash: db file offset overflow\n");
+ exits("overflow");
+ }
+
/* allocate an array large enough for worst case */
hlen = 2*n+1;
n = hlen*NDBPLEN + hlen*2*NDBPLEN;
ht = mallocz(n, 1);
- if(ht == 0){
+ if(ht == nil){
fprint(2, "mkhash: not enough memory\n");
- exits(syserr());
+ exits("not enougth memory");
}
for(p = ht; p < &ht[n]; p += NDBPLEN)
NDBPUTP(NDBNAP, p);
@@ -124,32 +123,36 @@
}
/* create the hash file */
- snprint(file, sizeof(file), "%s.%s", argv[1], argv[2]);
- fd = create(file, ORDWR, 0664);
+ file = smprint("%s.%s", argv[1], argv[2]);
+ fd = create(file, OWRITE, DMTMP|0664);
if(fd < 0){
- fprint(2, "mkhash: can't create %s\n", file);
- exits(syserr());
+ errstr(err, sizeof(err));
+ fprint(2, "mkhash: can't create %s: %s\n", file, err);
+ exits(err);
}
NDBPUTUL(db->mtime, buf);
NDBPUTUL(hlen, buf+NDBULLEN);
if(write(fd, buf, NDBHLEN) != NDBHLEN){
- fprint(2, "mkhash: writing %s\n", file);
- exits(syserr());
+ errstr(err, sizeof(err));
+ fprint(2, "mkhash: writing %s: %s\n", file, err);
+ remove(file);
+ exits(err);
}
if(write(fd, ht, nextchain) != nextchain){
- fprint(2, "mkhash: writing %s\n", file);
- exits(syserr());
+ errstr(err, sizeof(err));
+ fprint(2, "mkhash: writing %s: %s\n", file, err);
+ remove(file);
+ exits(err);
}
close(fd);
/* make sure file didn't change while we were making the hash */
d = dirstat(argv[1]);
- if(d == nil || d->qid.path != db->qid.path
- || d->qid.vers != db->qid.vers){
+ if(d == nil || d->qid.path != db->qid.path || d->qid.vers != db->qid.vers){
fprint(2, "mkhash: %s changed underfoot\n", argv[1]);
remove(file);
exits("changed");
}
- exits(0);
+ exits(nil);
}