Use UnrealDB functions in channeldb.

pull/1/head
Bram Matthys 2 years ago
parent 40ace27e7d
commit 30d64f2ebe
No known key found for this signature in database
GPG Key ID: BF8116B163EAAE98

@ -35,14 +35,14 @@ ModuleHeader MOD_HEADER = {
do { \
sendto_realops_and_log("[channeldb] Error writing to temporary database file " \
"'%s': %s (DATABASE NOT SAVED)", \
fname, strerror(errno)); \
fname, unrealdb_get_error_string()); \
} while(0)
#define W_SAFE(x) \
do { \
if (!(x)) { \
WARN_WRITE_ERROR(tmpfname); \
fclose(fd); \
unrealdb_close(db); \
return 0; \
} \
} while(0)
@ -55,31 +55,39 @@ ModuleHeader MOD_HEADER = {
} \
} while(0)
/* Structs */
struct cfgstruct {
char *database;
char *db_secret;
};
/* Forward declarations */
void channeldb_moddata_free(ModData *md);
void setcfg(void);
void freecfg(void);
int channeldb_configtest(ConfigFile *cf, ConfigEntry *ce, int type, int *errs);
int channeldb_configrun(ConfigFile *cf, ConfigEntry *ce, int type);
void setcfg(struct cfgstruct *cfg);
void freecfg(struct cfgstruct *cfg);
int channeldb_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs);
int channeldb_config_posttest(int *errs);
int channeldb_config_run(ConfigFile *cf, ConfigEntry *ce, int type);
EVENT(write_channeldb_evt);
int write_channeldb(void);
int write_channel_entry(FILE *fd, const char *tmpfname, Channel *channel);
int write_channel_entry(UnrealDB *db, const char *tmpfname, Channel *channel);
int read_channeldb(void);
static void set_channel_mode(Channel *channel, char *modes, char *parameters);
/* Global variables */
static uint32_t channeldb_version = CHANNELDB_VERSION;
struct cfgstruct {
char *database;
};
static struct cfgstruct cfg;
static struct cfgstruct test;
static long channeldb_next_event = 0;
MOD_TEST()
{
memset(&cfg, 0, sizeof(cfg));
HookAdd(modinfo->handle, HOOKTYPE_CONFIGTEST, 0, channeldb_configtest);
memset(&test, 0, sizeof(test));
setcfg(&test);
HookAdd(modinfo->handle, HOOKTYPE_CONFIGTEST, 0, channeldb_config_test);
HookAdd(modinfo->handle, HOOKTYPE_CONFIGPOSTTEST, 0, channeldb_config_posttest);
return MOD_SUCCESS;
}
@ -89,9 +97,9 @@ MOD_INIT()
LoadPersistentLong(modinfo, channeldb_next_event);
setcfg();
setcfg(&cfg);
HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, channeldb_configrun);
HookAdd(modinfo->handle, HOOKTYPE_CONFIGRUN, 0, channeldb_config_run);
return MOD_SUCCESS;
}
@ -122,7 +130,8 @@ MOD_LOAD()
MOD_UNLOAD()
{
freecfg();
freecfg(&test);
freecfg(&cfg);
SavePersistentLong(modinfo, channeldb_next_event);
return MOD_SUCCESS;
}
@ -133,19 +142,20 @@ void channeldb_moddata_free(ModData *md)
md->i = 0;
}
void setcfg(void)
void setcfg(struct cfgstruct *cfg)
{
// Default: data/channel.db
safe_strdup(cfg.database, "channel.db");
convert_to_absolute_path(&cfg.database, PERMDATADIR);
safe_strdup(cfg->database, "channel.db");
convert_to_absolute_path(&cfg->database, PERMDATADIR);
}
void freecfg(void)
void freecfg(struct cfgstruct *cfg)
{
safe_free(cfg.database);
safe_free(cfg->database);
safe_free(cfg->db_secret);
}
int channeldb_configtest(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
int channeldb_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
{
int errors = 0;
ConfigEntry *cep;
@ -159,16 +169,45 @@ int channeldb_configtest(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
for (cep = ce->ce_entries; cep; cep = cep->ce_next)
{
if (!cep->ce_vardata) {
if (!cep->ce_vardata)
{
config_error("%s:%i: blank set::channeldb::%s without value", cep->ce_fileptr->cf_filename, cep->ce_varlinenum, cep->ce_varname);
errors++;
continue;
}
if (!strcmp(cep->ce_varname, "database")) {
} else
if (!strcmp(cep->ce_varname, "database"))
{
convert_to_absolute_path(&cep->ce_vardata, PERMDATADIR);
continue;
safe_strdup(test.database, cep->ce_vardata);
} else
if (!strcmp(cep->ce_varname, "db-secret"))
{
char *err;
if ((err = unrealdb_test_secret(cep->ce_vardata)))
{
config_error("%s:%i: set::channeldb::db-secret: %s", cep->ce_fileptr->cf_filename, cep->ce_varlinenum, err);
errors++;
continue;
}
safe_strdup(test.db_secret, cep->ce_vardata);
} else
{
config_error("%s:%i: unknown directive set::channeldb::%s", cep->ce_fileptr->cf_filename, cep->ce_varlinenum, cep->ce_varname);
errors++;
}
config_error("%s:%i: unknown directive set::channeldb::%s", cep->ce_fileptr->cf_filename, cep->ce_varlinenum, cep->ce_varname);
}
*errs = errors;
return errors ? -1 : 1;
}
int channeldb_config_posttest(int *errs)
{
int errors = 0;
char *errstr;
if (test.database && ((errstr = unrealdb_test_db(test.database, test.db_secret))))
{
config_error("[channeldb] %s", errstr);
errors++;
}
@ -176,7 +215,7 @@ int channeldb_configtest(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
return errors ? -1 : 1;
}
int channeldb_configrun(ConfigFile *cf, ConfigEntry *ce, int type)
int channeldb_config_run(ConfigFile *cf, ConfigEntry *ce, int type)
{
ConfigEntry *cep;
@ -191,6 +230,8 @@ int channeldb_configrun(ConfigFile *cf, ConfigEntry *ce, int type)
{
if (!strcmp(cep->ce_varname, "database"))
safe_strdup(cfg.database, cep->ce_vardata);
else if (!strcmp(cep->ce_varname, "db-secret"))
safe_strdup(cfg.db_secret, cep->ce_vardata);
}
return 1;
}
@ -206,7 +247,7 @@ EVENT(write_channeldb_evt)
int write_channeldb(void)
{
char tmpfname[512];
FILE *fd;
UnrealDB *db;
Channel *channel;
int cnt = 0;
#ifdef BENCHMARK
@ -217,33 +258,33 @@ int write_channeldb(void)
// Write to a tempfile first, then rename it if everything succeeded
snprintf(tmpfname, sizeof(tmpfname), "%s.%x.tmp", cfg.database, getrandom32());
fd = fopen(tmpfname, "wb");
if (!fd)
db = unrealdb_open(tmpfname, UNREALDB_MODE_WRITE, cfg.db_secret);
if (!db)
{
WARN_WRITE_ERROR(tmpfname);
return 0;
}
W_SAFE(write_data(fd, &channeldb_version, sizeof(channeldb_version)));
W_SAFE(unrealdb_write_data(db, &channeldb_version, sizeof(channeldb_version)));
/* First, count +P channels and write the count to the database */
for (channel = channels; channel; channel=channel->nextch)
if (has_channel_mode(channel, 'P'))
cnt++;
W_SAFE(write_int64(fd, cnt));
W_SAFE(unrealdb_write_int64(db, cnt));
for (channel = channels; channel; channel=channel->nextch)
{
/* We only care about +P (persistent) channels */
if (has_channel_mode(channel, 'P'))
{
if (!write_channel_entry(fd, tmpfname, channel))
if (!write_channel_entry(db, tmpfname, channel))
return 0;
}
}
// Everything seems to have gone well, attempt to close and rename the tempfile
if (fclose(fd) != 0)
if (!unrealdb_close(db))
{
WARN_WRITE_ERROR(tmpfname);
return 0;
@ -266,7 +307,7 @@ int write_channeldb(void)
return 1;
}
int write_listmode(FILE *fd, const char *tmpfname, Ban *lst)
int write_listmode(UnrealDB *db, const char *tmpfname, Ban *lst)
{
Ban *l;
int cnt = 0;
@ -274,50 +315,50 @@ int write_listmode(FILE *fd, const char *tmpfname, Ban *lst)
/* First count and write the list count */
for (l = lst; l; l = l->next)
cnt++;
W_SAFE(write_int32(fd, cnt));
W_SAFE(unrealdb_write_int32(db, cnt));
for (l = lst; l; l = l->next)
{
/* The entry, setby, seton */
W_SAFE(write_str(fd, l->banstr));
W_SAFE(write_str(fd, l->who));
W_SAFE(write_int64(fd, l->when));
W_SAFE(unrealdb_write_str(db, l->banstr));
W_SAFE(unrealdb_write_str(db, l->who));
W_SAFE(unrealdb_write_int64(db, l->when));
}
return 1;
}
int write_channel_entry(FILE *fd, const char *tmpfname, Channel *channel)
int write_channel_entry(UnrealDB *db, const char *tmpfname, Channel *channel)
{
W_SAFE(write_int32(fd, MAGIC_CHANNEL_START));
W_SAFE(unrealdb_write_int32(db, MAGIC_CHANNEL_START));
/* Channel name */
W_SAFE(write_str(fd, channel->chname));
W_SAFE(unrealdb_write_str(db, channel->chname));
/* Channel creation time */
W_SAFE(write_int64(fd, channel->creationtime));
W_SAFE(unrealdb_write_int64(db, channel->creationtime));
/* Topic (topic, setby, seton) */
W_SAFE(write_str(fd, channel->topic));
W_SAFE(write_str(fd, channel->topic_nick));
W_SAFE(write_int64(fd, channel->topic_time));
W_SAFE(unrealdb_write_str(db, channel->topic));
W_SAFE(unrealdb_write_str(db, channel->topic_nick));
W_SAFE(unrealdb_write_int64(db, channel->topic_time));
/* Basic channel modes (eg: +sntkl key 55) */
channel_modes(&me, modebuf, parabuf, sizeof(modebuf), sizeof(parabuf), channel);
W_SAFE(write_str(fd, modebuf));
W_SAFE(write_str(fd, parabuf));
W_SAFE(unrealdb_write_str(db, modebuf));
W_SAFE(unrealdb_write_str(db, parabuf));
/* Mode lock */
W_SAFE(write_str(fd, channel->mode_lock));
W_SAFE(unrealdb_write_str(db, channel->mode_lock));
/* List modes (bans, exempts, invex) */
if (!write_listmode(fd, tmpfname, channel->banlist))
if (!write_listmode(db, tmpfname, channel->banlist))
return 0;
if (!write_listmode(fd, tmpfname, channel->exlist))
if (!write_listmode(db, tmpfname, channel->exlist))
return 0;
if (!write_listmode(fd, tmpfname, channel->invexlist))
if (!write_listmode(db, tmpfname, channel->invexlist))
return 0;
W_SAFE(write_int32(fd, MAGIC_CHANNEL_END));
W_SAFE(unrealdb_write_int32(db, MAGIC_CHANNEL_END));
return 1;
}
#define R_SAFE(x) \
do { \
if (!(x)) { \
config_warn("[channeldb] Read error from database file '%s' (possible corruption): %s", cfg.database, strerror(errno)); \
config_warn("[channeldb] Read error from database file '%s' (possible corruption): %s", cfg.database, unrealdb_get_error_string()); \
if (e) \
{ \
safe_free(e->banstr); \
@ -328,21 +369,21 @@ int write_channel_entry(FILE *fd, const char *tmpfname, Channel *channel)
} \
} while(0)
int read_listmode(FILE *fd, Ban **lst)
int read_listmode(UnrealDB *db, Ban **lst)
{
uint32_t total;
uint64_t when;
int i;
Ban *e = NULL;
R_SAFE(read_data(fd, &total, sizeof(total)));
R_SAFE(unrealdb_read_data(db, &total, sizeof(total)));
for (i = 0; i < total; i++)
{
e = safe_alloc(sizeof(Ban));
R_SAFE(read_str(fd, &e->banstr));
R_SAFE(read_str(fd, &e->who));
R_SAFE(read_data(fd, &when, sizeof(when)));
R_SAFE(unrealdb_read_str(db, &e->banstr));
R_SAFE(unrealdb_read_str(db, &e->who));
R_SAFE(unrealdb_read_data(db, &when, sizeof(when)));
e->when = when;
e->next = *lst;
*lst = e;
@ -366,8 +407,8 @@ int read_listmode(FILE *fd, Ban **lst)
#define R_SAFE(x) \
do { \
if (!(x)) { \
config_warn("[channeldb] Read error from database file '%s' (possible corruption): %s", cfg.database, strerror(errno)); \
fclose(fd); \
config_warn("[channeldb] Read error from database file '%s' (possible corruption): %s", cfg.database, unrealdb_get_error_string()); \
unrealdb_close(db); \
FreeChannelEntry(); \
return 0; \
} \
@ -375,7 +416,7 @@ int read_listmode(FILE *fd, Ban **lst)
int read_channeldb(void)
{
FILE *fd;
UnrealDB *db;
uint32_t version;
int added = 0;
int i;
@ -397,29 +438,41 @@ int read_channeldb(void)
gettimeofday(&tv_alpha, NULL);
#endif
fd = fopen(cfg.database, "rb");
if (!fd)
db = unrealdb_open(cfg.database, UNREALDB_MODE_READ, cfg.db_secret);
if (!db)
{
if (errno == ENOENT)
if (unrealdb_get_error_code() == UNREALDB_ERROR_FILENOTFOUND)
{
/* Database does not exist. Could be first boot */
config_warn("[channeldb] No database present at '%s', will start a new one", cfg.database);
return 1;
} else {
config_warn("[channeldb] Unable to open the database file '%s' for reading: %s", cfg.database, strerror(errno));
} else
if (unrealdb_get_error_code() == UNREALDB_ERROR_NOTCRYPTED)
{
/* Re-open as unencrypted */
db = unrealdb_open(cfg.database, UNREALDB_MODE_READ, NULL);
if (!db)
{
/* This should actually never happen, unless some weird I/O error */
config_warn("[channeldb] Unable to open the database file '%s': %s", cfg.database, unrealdb_get_error_string());
return 0;
}
} else
{
config_warn("[channeldb] Unable to open the database file '%s' for reading: %s", cfg.database, unrealdb_get_error_string());
return 0;
}
}
R_SAFE(read_data(fd, &version, sizeof(version)));
R_SAFE(unrealdb_read_data(db, &version, sizeof(version)));
if (version > channeldb_version)
{
config_warn("[channeldb] Database '%s' has a wrong version: expected it to be <= %u but got %u instead", cfg.database, channeldb_version, version);
fclose(fd);
unrealdb_close(db);
return 0;
}
R_SAFE(read_data(fd, &count, sizeof(count)));
R_SAFE(unrealdb_read_data(db, &count, sizeof(count)));
for (i=1; i <= count; i++)
{
@ -434,20 +487,20 @@ int read_channeldb(void)
mode_lock = NULL;
Channel *channel;
R_SAFE(read_data(fd, &magic, sizeof(magic)));
R_SAFE(unrealdb_read_data(db, &magic, sizeof(magic)));
if (magic != MAGIC_CHANNEL_START)
{
config_error("[channeldb] Corrupt database (%s) - channel magic start is 0x%x. Further reading aborted.", cfg.database, magic);
break;
}
R_SAFE(read_str(fd, &chname));
R_SAFE(read_data(fd, &creationtime, sizeof(creationtime)));
R_SAFE(read_str(fd, &topic));
R_SAFE(read_str(fd, &topic_nick));
R_SAFE(read_data(fd, &topic_time, sizeof(topic_time)));
R_SAFE(read_str(fd, &modes1));
R_SAFE(read_str(fd, &modes2));
R_SAFE(read_str(fd, &mode_lock));
R_SAFE(unrealdb_read_str(db, &chname));
R_SAFE(unrealdb_read_data(db, &creationtime, sizeof(creationtime)));
R_SAFE(unrealdb_read_str(db, &topic));
R_SAFE(unrealdb_read_str(db, &topic_nick));
R_SAFE(unrealdb_read_data(db, &topic_time, sizeof(topic_time)));
R_SAFE(unrealdb_read_str(db, &modes1));
R_SAFE(unrealdb_read_str(db, &modes2));
R_SAFE(unrealdb_read_str(db, &mode_lock));
/* If we got this far, we can create/initialize the channel with the above */
channel = get_channel(&me, chname, CREATE);
channel->creationtime = creationtime;
@ -456,10 +509,10 @@ int read_channeldb(void)
channel->topic_time = topic_time;
safe_strdup(channel->mode_lock, mode_lock);
set_channel_mode(channel, modes1, modes2);
R_SAFE(read_listmode(fd, &channel->banlist));
R_SAFE(read_listmode(fd, &channel->exlist));
R_SAFE(read_listmode(fd, &channel->invexlist));
R_SAFE(read_data(fd, &magic, sizeof(magic)));
R_SAFE(read_listmode(db, &channel->banlist));
R_SAFE(read_listmode(db, &channel->exlist));
R_SAFE(read_listmode(db, &channel->invexlist));
R_SAFE(unrealdb_read_data(db, &magic, sizeof(magic)));
FreeChannelEntry();
added++;
if (magic != MAGIC_CHANNEL_END)
@ -469,7 +522,7 @@ int read_channeldb(void)
}
}
fclose(fd);
unrealdb_close(db);
if (added)
sendto_realops_and_log("[channeldb] Added %d persistent channels (+P)", added);

Loading…
Cancel
Save