From ca3bbfeadf2a785c87591aed7aa1438adb5e9026 Mon Sep 17 00:00:00 2001 From: k4be Date: Fri, 27 Aug 2021 12:20:36 +0200 Subject: [PATCH] Improve handling of missing files --- include/h.h | 3 +- src/conf.c | 2 +- src/misc.c | 15 +++++++ src/modules/geoip_classic.c | 64 +++++++++++++++++++----------- src/modules/geoip_csv.c | 78 +++++++++++++++++++++++-------------- 5 files changed, 107 insertions(+), 55 deletions(-) diff --git a/include/h.h b/include/h.h index a9c4d68f3..dbadbd17d 100644 --- a/include/h.h +++ b/include/h.h @@ -898,7 +898,7 @@ extern int is_valid_ip(char *str); extern int ipv6_capable(void); extern MODVAR Client *remote_rehash_client; extern MODVAR int debugfd; -extern void convert_to_absolute_path(char **path, char *reldir); +extern void convert_to_absolute_path(char **path, const char *reldir); extern int has_user_mode(Client *acptr, char mode); extern int has_channel_mode(Channel *channel, char mode); extern Cmode_t get_extmode_bitbychar(char m); @@ -1060,6 +1060,7 @@ extern int terminal_supports_color(void); extern void skip_whitespace(char **p); extern void read_until(char **p, char *stopchars); extern int is_ip_valid(const char *ip); +extern int is_file_readable(const char *file, const char *dir); /* src/unrealdb.c start */ extern UnrealDB *unrealdb_open(const char *filename, UnrealDBMode mode, char *secret_block); extern int unrealdb_close(UnrealDB *c); diff --git a/src/conf.c b/src/conf.c index ff9cc2b4a..f172fc012 100644 --- a/src/conf.c +++ b/src/conf.c @@ -3275,7 +3275,7 @@ char *pretty_time_val(long timeval) } /* This converts a relative path to an absolute path, but only if necessary. */ -void convert_to_absolute_path(char **path, char *reldir) +void convert_to_absolute_path(char **path, const char *reldir) { char *s; diff --git a/src/misc.c b/src/misc.c index 2c20f7a65..c6d495799 100644 --- a/src/misc.c +++ b/src/misc.c @@ -2360,3 +2360,18 @@ int is_ip_valid(const char *ip) return 0; } +/* + * Checks whether a file can be opened for reading. + */ +int is_file_readable(const char *file, const char *dir) +{ + char *filename = strdup(file); + convert_to_absolute_path(&filename, dir); + if (access(filename, R_OK)){ + safe_free(filename); + return 0; + } + safe_free(filename); + return 1; +} + diff --git a/src/modules/geoip_classic.c b/src/modules/geoip_classic.c index 743b2e93b..f41ba4725 100644 --- a/src/modules/geoip_classic.c +++ b/src/modules/geoip_classic.c @@ -63,15 +63,12 @@ int geoip_classic_configtest(ConfigFile *cf, ConfigEntry *ce, int type, int *err config_error("%s:%i: duplicate item set::geoip-classic::%s", cep->file->filename, cep->line_number, cep->name); continue; } - char *filename = strdup(cep->value); - convert_to_absolute_path(&filename, PERMDATADIR); - if(access(filename, R_OK)){ - config_error("%s:%i: set::geoip-classic::%s: cannot open file \"%s\" for reading", cep->file->filename, cep->line_number, cep->name, cep->value); + if (!is_file_readable(cep->value, PERMDATADIR)) + { + config_error("%s:%i: set::geoip-classic::%s: cannot open file \"%s/%s\" for reading (%s)", cep->file->filename, cep->line_number, cep->name, PERMDATADIR, cep->value, strerror(errno)); errors++; - safe_free(filename); continue; } - safe_free(filename); geoip_classic_config.have_ipv4_database = 1; continue; } @@ -82,15 +79,12 @@ int geoip_classic_configtest(ConfigFile *cf, ConfigEntry *ce, int type, int *err config_error("%s:%i: duplicate item set::geoip-classic::%s", cep->file->filename, cep->line_number, cep->name); continue; } - char *filename = strdup(cep->value); - convert_to_absolute_path(&filename, PERMDATADIR); - if(access(filename, R_OK)){ - config_error("%s:%i: set::geoip-classic::%s: cannot open file \"%s\" for reading", cep->file->filename, cep->line_number, cep->name, cep->value); + if (!is_file_readable(cep->value, PERMDATADIR)) + { + config_error("%s:%i: set::geoip-classic::%s: cannot open file \"%s/%s\" for reading (%s)", cep->file->filename, cep->line_number, cep->name, PERMDATADIR, cep->value, strerror(errno)); errors++; - safe_free(filename); continue; } - safe_free(filename); geoip_classic_config.have_ipv6_database = 1; continue; } @@ -104,10 +98,40 @@ int geoip_classic_configtest(ConfigFile *cf, ConfigEntry *ce, int type, int *err int geoip_classic_configposttest(int *errs) { int errors = 0; - if (geoip_classic_config.have_config && !geoip_classic_config.have_ipv4_database && !geoip_classic_config.have_ipv6_database) + if (geoip_classic_config.have_config) { - config_error("geoip_classic: no database files specified! Remove set::geoip-classic to use defaults"); - errors++; + if (!geoip_classic_config.have_ipv4_database && !geoip_classic_config.have_ipv6_database) + { + config_error("geoip_classic: no database files specified! Remove set::geoip-classic to use defaults"); + errors++; + } + } else + { + safe_strdup(geoip_classic_config.v4_db_file, "GeoIP.dat"); + safe_strdup(geoip_classic_config.v6_db_file, "GeoIPv6.dat"); + + if (is_file_readable(geoip_classic_config.v4_db_file, PERMDATADIR)) + { + geoip_classic_config.have_ipv4_database = 1; + } else + { + config_warn("[geoip_classic] cannot open IPv4 database file \"%s/%s\" for reading (%s)", PERMDATADIR, geoip_classic_config.v4_db_file, strerror(errno)); + safe_free(geoip_classic_config.v4_db_file); + } + if (is_file_readable(geoip_classic_config.v6_db_file, PERMDATADIR)) + { + geoip_classic_config.have_ipv6_database = 1; + } else + { + config_warn("[geoip_classic] cannot open IPv6 database file \"%s/%s\" for reading (%s)", PERMDATADIR, geoip_classic_config.v6_db_file, strerror(errno)); + safe_free(geoip_classic_config.v6_db_file); + } + if (!geoip_classic_config.have_ipv4_database && !geoip_classic_config.have_ipv6_database) + { + config_error("[geoip_classic] couldn't read any database! Either put these in %s location " + "or specify another in set::geoip-classic config block", PERMDATADIR); + errors++; + } } *errs = errors; @@ -129,9 +153,9 @@ int geoip_classic_configrun(ConfigFile *cf, ConfigEntry *ce, int type) for (cep = ce->items; cep; cep = cep->next) { - if (!strcmp(cep->name, "ipv4-database")) + if (!strcmp(cep->name, "ipv4-database") && geoip_classic_config.have_ipv4_database) safe_strdup(geoip_classic_config.v4_db_file, cep->value); - if (!strcmp(cep->name, "ipv6-database")) + if (!strcmp(cep->name, "ipv6-database") && geoip_classic_config.have_ipv6_database) safe_strdup(geoip_classic_config.v6_db_file, cep->value); } return 1; @@ -169,12 +193,6 @@ MOD_LOAD() { int found_good_file = 0; - if (!geoip_classic_config.have_config) - { - safe_strdup(geoip_classic_config.v4_db_file, "GeoIP.dat"); - safe_strdup(geoip_classic_config.v6_db_file, "GeoIPv6.dat"); - } - if (geoip_classic_config.v4_db_file) { convert_to_absolute_path(&geoip_classic_config.v4_db_file, PERMDATADIR); diff --git a/src/modules/geoip_csv.c b/src/modules/geoip_csv.c index 1452e2a3d..18b14553c 100644 --- a/src/modules/geoip_csv.c +++ b/src/modules/geoip_csv.c @@ -115,15 +115,12 @@ int geoip_csv_configtest(ConfigFile *cf, ConfigEntry *ce, int type, int *errs) config_error("%s:%i: duplicate item set::geoip-csv::%s", cep->file->filename, cep->line_number, cep->name); continue; } - char *filename = strdup(cep->value); - convert_to_absolute_path(&filename, PERMDATADIR); - if(access(filename, R_OK)){ - config_error("%s:%i: set::geoip-classic::%s: cannot open file \"%s\" for reading", cep->file->filename, cep->line_number, cep->name, cep->value); + if (!is_file_readable(cep->value, PERMDATADIR)) + { + config_error("%s:%i: set::geoip-csv::%s: cannot open file \"%s/%s\" for reading (%s)", cep->file->filename, cep->line_number, cep->name, PERMDATADIR, cep->value, strerror(errno)); errors++; - safe_free(filename); continue; } - safe_free(filename); geoip_csv_config.have_ipv4_database = 1; continue; } @@ -134,15 +131,12 @@ int geoip_csv_configtest(ConfigFile *cf, ConfigEntry *ce, int type, int *errs) config_error("%s:%i: duplicate item set::geoip-csv::%s", cep->file->filename, cep->line_number, cep->name); continue; } - char *filename = strdup(cep->value); - convert_to_absolute_path(&filename, PERMDATADIR); - if(access(filename, R_OK)){ - config_error("%s:%i: set::geoip-csv::%s: cannot open file \"%s\" for reading", cep->file->filename, cep->line_number, cep->name, cep->value); + if (!is_file_readable(cep->value, PERMDATADIR)) + { + config_error("%s:%i: set::geoip-csv::%s: cannot open file \"%s/%s\" for reading (%s)", cep->file->filename, cep->line_number, cep->name, PERMDATADIR, cep->value, strerror(errno)); errors++; - safe_free(filename); continue; } - safe_free(filename); geoip_csv_config.have_ipv6_database = 1; continue; } @@ -153,16 +147,13 @@ int geoip_csv_configtest(ConfigFile *cf, ConfigEntry *ce, int type, int *errs) config_error("%s:%i: duplicate item set::geoip-csv::%s", cep->file->filename, cep->line_number, cep->name); continue; } - char *filename = strdup(cep->value); - convert_to_absolute_path(&filename, PERMDATADIR); - if(access(filename, R_OK)){ - config_error("%s:%i: set::geoip-csv::%s: cannot open file \"%s\" for reading", cep->file->filename, cep->line_number, cep->name, cep->value); + if (!is_file_readable(cep->value, PERMDATADIR)) + { + config_error("%s:%i: set::geoip-csv::%s: cannot open file \"%s/%s\" for reading (%s)", cep->file->filename, cep->line_number, cep->name, PERMDATADIR, cep->value, strerror(errno)); errors++; - safe_free(filename); continue; } - safe_free(filename); - geoip_csv_config.have_ipv6_database = 1; + geoip_csv_config.have_countries = 1; continue; } config_warn("%s:%i: unknown item set::geoip-csv::%s", cep->file->filename, cep->line_number, cep->name); @@ -179,12 +170,46 @@ int geoip_csv_configposttest(int *errs) { if (!geoip_csv_config.have_countries) { - config_error("geoip_csv: no countries file specified! Remove set::geoip-csv to use defaults"); + config_error("[geoip_csv] no countries file specified! Remove set::geoip-csv to use defaults"); errors++; } if (!geoip_csv_config.have_ipv4_database && !geoip_csv_config.have_ipv6_database) { - config_error("geoip_csv: no database files specified! Remove set::geoip-csv to use defaults"); + config_error("[geoip_csv] no database files specified! Remove set::geoip-csv to use defaults"); + errors++; + } + } else + { + safe_strdup(geoip_csv_config.v4_db_file, "GeoLite2-Country-Blocks-IPv4.csv"); + safe_strdup(geoip_csv_config.v6_db_file, "GeoLite2-Country-Blocks-IPv6.csv"); + safe_strdup(geoip_csv_config.countries_db_file, "GeoLite2-Country-Locations-en.csv"); + + if (is_file_readable(geoip_csv_config.v4_db_file, PERMDATADIR)) + { + geoip_csv_config.have_ipv4_database = 1; + } else + { + config_warn("[geoip_csv] cannot open IPv4 blocks file \"%s/%s\" for reading (%s)", PERMDATADIR, geoip_csv_config.v4_db_file, strerror(errno)); + safe_free(geoip_csv_config.v4_db_file); + } + if (is_file_readable(geoip_csv_config.v6_db_file, PERMDATADIR)) + { + geoip_csv_config.have_ipv6_database = 1; + } else + { + config_warn("[geoip_csv] cannot open IPv6 blocks file \"%s/%s\" for reading (%s)", PERMDATADIR, geoip_csv_config.v6_db_file, strerror(errno)); + safe_free(geoip_csv_config.v6_db_file); + } + if (!is_file_readable(geoip_csv_config.countries_db_file, PERMDATADIR)) + { + config_error("[geoip_csv] cannot open countries file \"%s/%s\" for reading (%s)", PERMDATADIR, geoip_csv_config.countries_db_file, strerror(errno)); + safe_free(geoip_csv_config.countries_db_file); + errors++; + } + if (!geoip_csv_config.have_ipv4_database && !geoip_csv_config.have_ipv6_database) + { + config_error("[geoip_csv] couldn't read any blocks file! Either put these in %s location " + "or specify another in set::geoip-csv config block", PERMDATADIR); errors++; } } @@ -208,9 +233,9 @@ int geoip_csv_configrun(ConfigFile *cf, ConfigEntry *ce, int type) for (cep = ce->items; cep; cep = cep->next) { - if (!strcmp(cep->name, "ipv4-blocks-file")) + if (!strcmp(cep->name, "ipv4-blocks-file") && geoip_csv_config.have_ipv4_database) safe_strdup(geoip_csv_config.v4_db_file, cep->value); - if (!strcmp(cep->name, "ipv6-blocks-file")) + if (!strcmp(cep->name, "ipv6-blocks-file") && geoip_csv_config.have_ipv6_database) safe_strdup(geoip_csv_config.v6_db_file, cep->value); if (!strcmp(cep->name, "countries-file")) safe_strdup(geoip_csv_config.countries_db_file, cep->value); @@ -251,13 +276,6 @@ MOD_LOAD() { int found_good_file = 0; - if (!geoip_csv_config.have_config) - { - safe_strdup(geoip_csv_config.v4_db_file, "GeoLite2-Country-Blocks-IPv4.csv"); - safe_strdup(geoip_csv_config.v6_db_file, "GeoLite2-Country-Blocks-IPv6.csv"); - safe_strdup(geoip_csv_config.countries_db_file, "GeoLite2-Country-Locations-en.csv"); - } - if (geoip_csv_config.v4_db_file) { convert_to_absolute_path(&geoip_csv_config.v4_db_file, PERMDATADIR);