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

24
cdb.c
View File

@ -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;

View File

@ -3,6 +3,7 @@
#include <string.h>
#include <stdlib.h> // 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

View File

@ -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);

1
dump.h
View File

@ -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)

127
infobot.c
View File

@ -3,25 +3,13 @@
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <fnmatch.h>
#include <ctype.h>
#include <sys/time.h>
#include <sysexits.h>
#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;