1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
|
#include <unistd.h>
#include <stdio.h>
#include "strerr.h"
#include "error.h"
#include "buffer.h"
#include "open.h"
#include "cdb.h"
#include "cdb_make.h"
#include "fmt.h"
#define USAGE " cdb cdb.tmp"
#define FATAL "cdbmake: fatal: "
const char *progname;
static struct cdb_make c;
char *cdb;
char *tmp;
int entry;
char ch;
void usage() { strerr_die4x(100, "usage: ", progname, USAGE, "\n"); }
void die_write() { strerr_die4sys(111, FATAL, "unable to create ", tmp,": "); }
void die_read(const char *e) {
char s[FMT_ULONG];
s[fmt_ulong(s, entry)] =0;
strerr_die5x(111, FATAL, "unable to read input: entry ", s, ": ", e);
}
inline void getch() {
switch(buffer_GETC(buffer_0, &ch)) {
case 0: die_read("unexpected end if input");
case -1: die_read(error_str(errno));
}
}
int main(int argc, char **argv) {
int fdtmp;
unsigned int keylen;
unsigned int datalen;
uint32 hash;
int i;
progname =*argv++;
if (argc != 3) usage();
cdb =*argv++;
if (!*cdb) usage();
tmp =*argv;
if (!*tmp) usage();
/* start cdb file */
if ((fdtmp =open_trunc(tmp)) == -1) die_write();
if (cdb_make_start(&c, fdtmp) == -1) die_write();
entry =0;
for (;;) {
/* read entry */
++entry;
getch();
if (ch == '\n') break; /* end of input */
if (ch != '+') die_read("entry must start with +");
/* read keylen */
keylen =0;
for (;;) {
getch();
if (ch == ',') break; /* end of keylen */
if ((ch < '0') || (ch > '9')) die_read("bad keylen format");
if (keylen > 429496720) { errno =error_nomem; die_write(); }
keylen =keylen *10 +(ch -'0');
}
/* read datalen */
datalen =0;
for (;;) {
getch();
if (ch == ':') break; /* end of datalen */
if ((ch < '0') || (ch > '9')) die_read("bad datalen format");
if (datalen > 429496720) { errno = error_nomem; die_write(); }
datalen =datalen *10 +(ch -'0');
}
/* start cdb entry */
if (cdb_make_addbegin(&c, keylen, datalen) == -1) die_write();
hash =CDB_HASHSTART;
/* write key */
for (i =0; i < keylen; ++i) {
getch(); if (buffer_PUTC(&c.b, ch) == -1) die_write();
hash =cdb_hashadd(hash, ch);
}
getch(); if (ch != '-') die_read("key must be followed by ->");
getch(); if (ch != '>') die_read("key must be followed by ->");
/* write data */
for (i =0; i < datalen; ++i) {
getch(); if (buffer_PUTC(&c.b, ch) == -1) die_write();
}
/* finish cdb entry */
if (cdb_make_addend(&c, keylen, datalen, hash) == -1) die_write();
/* next entry */
getch(); if (ch != '\n') die_read("newline expected");
}
/* finish cdb file */
if (cdb_make_finish(&c) == -1) die_write();
if ((fsync(fdtmp) == -1) || (close(fdtmp) == -1)) die_write();
if (rename(tmp, cdb) == -1)
strerr_die6sys(111, FATAL, "unable to rename ", tmp," to ", cdb, ": ");
_exit(0);
}
|