From b48152c085a98b499ac92098dc2f23bc9bf00a03 Mon Sep 17 00:00:00 2001 From: Neale Pickett Date: Wed, 21 Nov 2012 13:10:03 -0700 Subject: [PATCH] add remove action to infobot --- cdb.c | 24 +++++++---- cdbmake.c | 9 ++-- cdbmake.h | 1 + dump.h | 1 + infobot.c | 127 ++++++++++++++++++++++++++++++++++++++---------------- 5 files changed, 112 insertions(+), 50 deletions(-) diff --git a/cdb.c b/cdb.c index bc3c845..55a31e7 100644 --- a/cdb.c +++ b/cdb.c @@ -40,8 +40,10 @@ read_u32le(FILE *f) { uint8_t d[4]; - fread(d, 4, 1, f); - return ((d[0]<< 0) | + if (0 == fread(d, 4, 1, f)) { + return 0; + } + return ((d[0] << 0) | (d[1] << 8) | (d[2] << 16) | (d[3] << 24)); @@ -80,24 +82,26 @@ cdb_dump(struct cdb_ctx *ctx, // Find out where to stop reading int i; + fseek(ctx->f, 0, SEEK_SET); ctx->hash_len = 0; ctx->hash_pos = 0xffffffff; for (i = 0; i < 256; i += 1) { uint32_t p; - fseek(ctx->f, i * 8, SEEK_SET); p = read_u32le(ctx->f); + read_u32le(ctx->f); if (p < ctx->hash_pos) { ctx->hash_pos = p; } } - fseek(ctx->f, 256 * 8, SEEK_SET); - } else { - long where = ftell(ctx->f); - if (where >= ctx->hash_pos) { - return EOF; - } + ctx->entry = 256 * 8; + fseek(ctx->f, ctx->entry, SEEK_SET); + } + + // Stop if we've reached the end + if (ctx->entry >= ctx->hash_pos) { + return EOF; } // Read the two buffers @@ -107,6 +111,8 @@ cdb_dump(struct cdb_ctx *ctx, *keylen = read_buf(ctx->f, klen, key, *keylen); *vallen = read_buf(ctx->f, vlen, val, *vallen); + + ctx->entry += 4 + 4 + klen + vlen; } return 0; diff --git a/cdbmake.c b/cdbmake.c index 90bf787..437aa83 100644 --- a/cdbmake.c +++ b/cdbmake.c @@ -3,6 +3,7 @@ #include #include // XXX: remove if malloc() is gone #include "cdbmake.h" +#include "dump.h" static uint32_t hash(char *s, size_t len) @@ -36,7 +37,8 @@ cdbmake_init(struct cdbmake_ctx *ctx, FILE *f) ctx->nrecords[i] = 0; } - fseek(f, 256 * 8, SEEK_SET); + ctx->where = 256 * 8; + fseek(f, ctx->where, SEEK_SET); } void @@ -44,7 +46,6 @@ cdbmake_add(struct cdbmake_ctx *ctx, char *key, size_t keylen, char *val, size_t vallen) { - long where = ftell(ctx->f); uint32_t hashval = hash(key, keylen); int idx = hashval % 256; uint32_t n = ctx->nrecords[idx]; @@ -57,13 +58,15 @@ cdbmake_add(struct cdbmake_ctx *ctx, return; } ctx->records[idx][n].hashval = hashval; - ctx->records[idx][n].offset = (uint32_t)where; + ctx->records[idx][n].offset = (uint32_t)ctx->where; // Write it out write_u32le(ctx->f, keylen); write_u32le(ctx->f, vallen); fwrite(key, 1, keylen, ctx->f); fwrite(val, 1, vallen, ctx->f); + + ctx->where += 4 + 4 + keylen + vallen; } void diff --git a/cdbmake.h b/cdbmake.h index 5c21c25..b4814ae 100644 --- a/cdbmake.h +++ b/cdbmake.h @@ -15,6 +15,7 @@ struct cdbmake_ctx { FILE *f; struct cdbmake_record *records[256]; uint32_t nrecords[256]; + long where; }; void cdbmake_init(struct cdbmake_ctx *ctx, FILE *f); diff --git a/dump.h b/dump.h index b122fe0..3505e99 100644 --- a/dump.h +++ b/dump.h @@ -11,6 +11,7 @@ #endif #define DUMP() DUMPf("") #define DUMP_d(v) DUMPf("%s = %d", #v, v) +#define DUMP_l(v) DUMPf("%s = %ld", #v, v) #define DUMP_x(v) DUMPf("%s = 0x%x", #v, v) #define DUMP_s(v) DUMPf("%s = %s", #v, v) #define DUMP_c(v) DUMPf("%s = '%c' (0x%02x)", #v, v, v) diff --git a/infobot.c b/infobot.c index 382dde2..1723582 100644 --- a/infobot.c +++ b/infobot.c @@ -3,25 +3,13 @@ #include #include #include +#include #include #include #include #include "cdb.h" #include "cdbmake.h" - -/* Some things I use for debugging */ -#ifdef NODUMP -# define DUMPf(fmt, args...) -#else -# define DUMPf(fmt, args...) fprintf(stderr, "%s:%s:%d " fmt "\n", __FILE__, __FUNCTION__, __LINE__, ##args) -#endif -#define DUMP() DUMPf("") -#define DUMP_u(v) DUMPf("%s = %u", #v, v) -#define DUMP_d(v) DUMPf("%s = %d", #v, v) -#define DUMP_x(v) DUMPf("%s = 0x%x", #v, v) -#define DUMP_s(v) DUMPf("%s = %s", #v, v) -#define DUMP_c(v) DUMPf("%s = %c", #v, v) -#define DUMP_p(v) DUMPf("%s = %p", #v, v) +#include "dump.h" int usage() @@ -115,6 +103,45 @@ list(char *filename, char *key) return 0; } +static int +setup_copy(char *infn, struct cdb_ctx *inc, FILE **inf, + char **outfn, struct cdbmake_ctx *outc, FILE **outf) +{ + static char tmpfn[8192]; + + *inf = fopen(infn, "rb"); + if (! *inf) { + perror("Opening database"); + return EX_NOINPUT; + } + + snprintf(tmpfn, sizeof(tmpfn), "%s.%d", infn, getpid()); + *outf = fopen(tmpfn, "wb"); + if (! *outf) { + perror("Creating temporary database"); + return EX_CANTCREAT; + } + + cdb_init(inc, *inf); + cdbmake_init(outc, *outf); + + *outfn = strdup(tmpfn); + + return 0; +} + +static void +finish_copy(char *infn, struct cdb_ctx *inc, FILE **inf, + char *outfn, struct cdbmake_ctx *outc, FILE **outf) +{ + cdbmake_finalize(outc); + fclose(*outf); + fclose(*inf); + + rename(outfn, infn); + free(outfn); +} + int add(char *filename, char *key, char *val) { @@ -122,26 +149,14 @@ add(char *filename, char *key, char *val) struct cdbmake_ctx outc; FILE *inf; FILE *outf; - char tmpfn[8192]; + char *outfn; + int ret; - // Open input file - inf = fopen(filename, "rb"); - if (! inf) { - perror("Opening database"); - return EX_NOINPUT; + ret = setup_copy(filename, &inc, &inf, &outfn, &outc, &outf); + if (ret) { + return ret; } - // Create temporary output file - snprintf(tmpfn, sizeof(tmpfn), "%s.%d", filename, getpid()); - outf = fopen(tmpfn, "wb"); - if (! outf) { - perror("Creating temporary database"); - return EX_CANTCREAT; - } - - cdb_init(&inc, inf); - cdbmake_init(&outc, outf); - for (;;) { char key[8192]; char val[8192]; @@ -154,15 +169,52 @@ add(char *filename, char *key, char *val) cdbmake_add(&outc, key, keylen, val, vallen); } cdbmake_add(&outc, key, strlen(key), val, strlen(val)); - cdbmake_finalize(&outc); - fclose(outf); - fclose(inf); - rename(tmpfn, filename); + finish_copy(filename, &inc, &inf, outfn, &outc, &outf); return 0; } +int +del(char *filename, char *key, char *glob) +{ + size_t keylen = strlen(key); + struct cdb_ctx inc; + struct cdbmake_ctx outc; + FILE *inf; + FILE *outf; + char *outfn; + int ret; + + ret = setup_copy(filename, &inc, &inf, &outfn, &outc, &outf); + if (ret) { + return ret; + } + + for (;;) { + char k[8192]; + char v[8192]; + size_t klen = sizeof(k); + size_t vlen = sizeof(v) - 1; + + if (EOF == cdb_dump(&inc, k, &klen, v, &vlen)) { + break; + } + + v[vlen] = '\0'; + if ((klen == keylen) && + (0 == memcmp(k, key, klen)) && + (0 == fnmatch(glob, v, 0))) { + // Skip if it matches + } else { + cdbmake_add(&outc, k, klen, v, vlen); + } + } + + finish_copy(filename, &inc, &inf, outfn, &outc, &outf); + return 0; +} + enum action { ACT_ONE, @@ -223,9 +275,8 @@ main(int argc, char *argv[]) return list(filename, key); case ACT_ADD: return add(filename, key, val); - default: - fprintf(stderr, "Not yet implemented, chump %s.\n", val); - break; + case ACT_DEL: + return del(filename, key, val); } return 0;