add remove action to infobot

This commit is contained in:
Neale Pickett 2012-11-21 13:10:03 -07:00
parent b993629d88
commit b48152c085
5 changed files with 112 additions and 50 deletions

20
cdb.c
View File

@ -40,7 +40,9 @@ read_u32le(FILE *f)
{ {
uint8_t d[4]; uint8_t d[4];
fread(d, 4, 1, f); if (0 == fread(d, 4, 1, f)) {
return 0;
}
return ((d[0] << 0) | return ((d[0] << 0) |
(d[1] << 8) | (d[1] << 8) |
(d[2] << 16) | (d[2] << 16) |
@ -80,24 +82,26 @@ cdb_dump(struct cdb_ctx *ctx,
// Find out where to stop reading // Find out where to stop reading
int i; int i;
fseek(ctx->f, 0, SEEK_SET);
ctx->hash_len = 0; ctx->hash_len = 0;
ctx->hash_pos = 0xffffffff; ctx->hash_pos = 0xffffffff;
for (i = 0; i < 256; i += 1) { for (i = 0; i < 256; i += 1) {
uint32_t p; uint32_t p;
fseek(ctx->f, i * 8, SEEK_SET);
p = read_u32le(ctx->f); p = read_u32le(ctx->f);
read_u32le(ctx->f);
if (p < ctx->hash_pos) { if (p < ctx->hash_pos) {
ctx->hash_pos = p; ctx->hash_pos = p;
} }
} }
fseek(ctx->f, 256 * 8, SEEK_SET);
} else {
long where = ftell(ctx->f);
if (where >= ctx->hash_pos) { ctx->entry = 256 * 8;
return EOF; 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 // Read the two buffers
@ -107,6 +111,8 @@ cdb_dump(struct cdb_ctx *ctx,
*keylen = read_buf(ctx->f, klen, key, *keylen); *keylen = read_buf(ctx->f, klen, key, *keylen);
*vallen = read_buf(ctx->f, vlen, val, *vallen); *vallen = read_buf(ctx->f, vlen, val, *vallen);
ctx->entry += 4 + 4 + klen + vlen;
} }
return 0; return 0;

View File

@ -3,6 +3,7 @@
#include <string.h> #include <string.h>
#include <stdlib.h> // XXX: remove if malloc() is gone #include <stdlib.h> // XXX: remove if malloc() is gone
#include "cdbmake.h" #include "cdbmake.h"
#include "dump.h"
static uint32_t static uint32_t
hash(char *s, size_t len) hash(char *s, size_t len)
@ -36,7 +37,8 @@ cdbmake_init(struct cdbmake_ctx *ctx, FILE *f)
ctx->nrecords[i] = 0; ctx->nrecords[i] = 0;
} }
fseek(f, 256 * 8, SEEK_SET); ctx->where = 256 * 8;
fseek(f, ctx->where, SEEK_SET);
} }
void void
@ -44,7 +46,6 @@ cdbmake_add(struct cdbmake_ctx *ctx,
char *key, size_t keylen, char *key, size_t keylen,
char *val, size_t vallen) char *val, size_t vallen)
{ {
long where = ftell(ctx->f);
uint32_t hashval = hash(key, keylen); uint32_t hashval = hash(key, keylen);
int idx = hashval % 256; int idx = hashval % 256;
uint32_t n = ctx->nrecords[idx]; uint32_t n = ctx->nrecords[idx];
@ -57,13 +58,15 @@ cdbmake_add(struct cdbmake_ctx *ctx,
return; return;
} }
ctx->records[idx][n].hashval = hashval; 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 it out
write_u32le(ctx->f, keylen); write_u32le(ctx->f, keylen);
write_u32le(ctx->f, vallen); write_u32le(ctx->f, vallen);
fwrite(key, 1, keylen, ctx->f); fwrite(key, 1, keylen, ctx->f);
fwrite(val, 1, vallen, ctx->f); fwrite(val, 1, vallen, ctx->f);
ctx->where += 4 + 4 + keylen + vallen;
} }
void void

View File

@ -15,6 +15,7 @@ struct cdbmake_ctx {
FILE *f; FILE *f;
struct cdbmake_record *records[256]; struct cdbmake_record *records[256];
uint32_t nrecords[256]; uint32_t nrecords[256];
long where;
}; };
void cdbmake_init(struct cdbmake_ctx *ctx, FILE *f); void cdbmake_init(struct cdbmake_ctx *ctx, FILE *f);

1
dump.h
View File

@ -11,6 +11,7 @@
#endif #endif
#define DUMP() DUMPf("") #define DUMP() DUMPf("")
#define DUMP_d(v) DUMPf("%s = %d", #v, v) #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_x(v) DUMPf("%s = 0x%x", #v, v)
#define DUMP_s(v) DUMPf("%s = %s", #v, v) #define DUMP_s(v) DUMPf("%s = %s", #v, v)
#define DUMP_c(v) DUMPf("%s = '%c' (0x%02x)", #v, v, v) #define DUMP_c(v) DUMPf("%s = '%c' (0x%02x)", #v, v, v)

127
infobot.c
View File

@ -3,25 +3,13 @@
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <fnmatch.h>
#include <ctype.h> #include <ctype.h>
#include <sys/time.h> #include <sys/time.h>
#include <sysexits.h> #include <sysexits.h>
#include "cdb.h" #include "cdb.h"
#include "cdbmake.h" #include "cdbmake.h"
#include "dump.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)
int int
usage() usage()
@ -115,6 +103,45 @@ list(char *filename, char *key)
return 0; 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 int
add(char *filename, char *key, char *val) add(char *filename, char *key, char *val)
{ {
@ -122,26 +149,14 @@ add(char *filename, char *key, char *val)
struct cdbmake_ctx outc; struct cdbmake_ctx outc;
FILE *inf; FILE *inf;
FILE *outf; FILE *outf;
char tmpfn[8192]; char *outfn;
int ret;
// Open input file ret = setup_copy(filename, &inc, &inf, &outfn, &outc, &outf);
inf = fopen(filename, "rb"); if (ret) {
if (! inf) { return ret;
perror("Opening database");
return EX_NOINPUT;
} }
// 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 (;;) { for (;;) {
char key[8192]; char key[8192];
char val[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, keylen, val, vallen);
} }
cdbmake_add(&outc, key, strlen(key), val, strlen(val)); cdbmake_add(&outc, key, strlen(key), val, strlen(val));
cdbmake_finalize(&outc);
fclose(outf); finish_copy(filename, &inc, &inf, outfn, &outc, &outf);
fclose(inf);
rename(tmpfn, filename);
return 0; 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 { enum action {
ACT_ONE, ACT_ONE,
@ -223,9 +275,8 @@ main(int argc, char *argv[])
return list(filename, key); return list(filename, key);
case ACT_ADD: case ACT_ADD:
return add(filename, key, val); return add(filename, key, val);
default: case ACT_DEL:
fprintf(stderr, "Not yet implemented, chump %s.\n", val); return del(filename, key, val);
break;
} }
return 0; return 0;