mirror of https://github.com/nealey/irc-bot
add remove action to infobot
This commit is contained in:
parent
b993629d88
commit
b48152c085
20
cdb.c
20
cdb.c
|
@ -40,7 +40,9 @@ read_u32le(FILE *f)
|
|||
{
|
||||
uint8_t d[4];
|
||||
|
||||
fread(d, 4, 1, f);
|
||||
if (0 == fread(d, 4, 1, f)) {
|
||||
return 0;
|
||||
}
|
||||
return ((d[0] << 0) |
|
||||
(d[1] << 8) |
|
||||
(d[2] << 16) |
|
||||
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
1
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)
|
||||
|
|
127
infobot.c
127
infobot.c
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue