+ trie_compile(res->trie1, lock);
+ info("%s loaded: done in %us, %u entries", file, (uint32_t)(time(0) - now), count);
+ return true;
+}
+
+static bool strlist_create_from_rhbl(strlist_local_t *hosts, strlist_local_t *domains,
+ const char *file, int weight, bool lock)
+{
+ uint32_t host_count, domain_count;
+ file_map_t map;
+ const char *p, *end;
+ char line[BUFSIZ];
+ time_t now = time(0);
+
+ if (!file_map_open(&map, file, false)) {
+ return false;
+ }
+ p = map.map;
+ end = map.end;
+ while (end > p && end[-1] != '\n') {
+ --end;
+ }
+ if (end != map.end) {
+ warn("%s: final \\n missing, ignoring last line", file);
+ }
+
+
+ strlist_resource_t *res = resource_get("strlist", file);
+ if (res == NULL) {
+ res = p_new(strlist_resource_t, 1);
+ resource_set("strlist", file, res, (resource_destructor_t)strlist_resource_wipe);
+ } else if (res->trie2 == NULL) {
+ err("%s not loaded: the file is already used as a strlist-file parameter", file);
+ resource_release("strlist", file);
+ file_map_close(&map);
+ return false;
+ }
+
+ p_clear(hosts, 1);
+ hosts->filename = m_strdup(file);
+ hosts->db = &res->trie1;
+ hosts->weight = weight;
+ hosts->reverse = true;
+ host_count = 0;
+
+ p_clear(domains, 1);
+ /* don't set filename */
+ domains->db = &res->trie2;
+ domains->weight = weight;
+ domains->reverse = true;
+ domains->partial = true;
+ domain_count = 0;
+
+ if (map.st.st_size == res->size && map.st.st_mtime == res->mtime) {
+ info("%s loaded: already up-to-date", file);
+ file_map_close(&map);
+ return true;
+ }
+
+ trie_delete(&res->trie1);
+ trie_delete(&res->trie2);
+ res->trie1 = trie_new();
+ res->trie2 = trie_new();
+ res->size = map.st.st_size;
+ res->mtime = map.st.st_mtime;
+
+ while (p < end && p != NULL) {
+ const char *eol = (char *)memchr(p, '\n', end - p);
+ if (eol == NULL) {
+ eol = end;
+ }
+ if (eol - p >= BUFSIZ) {
+ err("%s not loaded: unreasonnable long line", file);
+ file_map_close(&map);
+ trie_delete(&res->trie1);
+ trie_delete(&res->trie2);
+ strlist_local_wipe(hosts);
+ return false;
+ }
+ if (*p != '#') {
+ const char *eos = eol;
+ while (p < eos && isspace(*p)) {
+ ++p;
+ }
+ while (p < eos && isspace(eos[-1])) {
+ --eos;
+ }
+ if (p < eos) {
+ if (isalnum(*p)) {
+ strlist_copy(line, p, eos - p, true);
+ trie_insert(res->trie1, line);
+ ++host_count;
+ } else if (*p == '*') {
+ ++p;
+ strlist_copy(line, p, eos - p, true);
+ trie_insert(res->trie2, line);
+ ++domain_count;
+ }
+ }
+ }
+ p = eol + 1;
+ }
+ file_map_close(&map);
+ if (host_count > 0) {
+ trie_compile(res->trie1, lock);
+ } else {
+ trie_delete(&res->trie1);
+ }
+ if (domain_count > 0) {
+ trie_compile(res->trie2, lock);
+ } else {
+ trie_delete(&res->trie2);
+ }
+ if (res->trie1 == NULL && res->trie2 == NULL) {
+ err("%s not loaded: no data found", file);
+ strlist_local_wipe(hosts);
+ return false;
+ }
+ info("%s loaded: done in %us, %u hosts, %u domains", file,
+ (uint32_t)(time(0) - now), host_count, domain_count);
+ return true;