#include #include "hostlist.h" #include "gzip.h" #include "helpers.h" // inplace tolower() and add to pool static bool addpool(strpool **hostlist, char **s, const char *end, int *ct) { char *p=*s; // comment line if ( *p == '#' || *p == ';' || *p == '/' || *p == '\r' || *p == '\n') { // advance until eol for (; pfilename) { time_t t = file_mod_time(hfile->filename); if (!t) { // stat() error DLOG_ERR("cannot access hostlist file '%s'. in-memory content remains unchanged.\n",hfile->filename); return true; } if (t==hfile->mod_time) return true; // up to date StrPoolDestroy(&hfile->hostlist); if (!AppendHostList(&hfile->hostlist, hfile->filename)) { StrPoolDestroy(&hfile->hostlist); return false; } hfile->mod_time=t; } return true; } static bool LoadHostLists(struct hostlist_files_head *list) { bool bres=true; struct hostlist_file *hfile; LIST_FOREACH(hfile, list, next) { if (!LoadHostList(hfile)) // at least one failed bres=false; } return bres; } bool NonEmptyHostlist(strpool **hostlist) { // add impossible hostname if the list is empty return *hostlist ? true : StrPoolAddStrLen(hostlist, "@&()", 4); } static void MakeAutolistsNonEmpty() { struct desync_profile_list *dpl; LIST_FOREACH(dpl, ¶ms.desync_profiles, next) { if (dpl->dp.hostlist_auto) NonEmptyHostlist(&dpl->dp.hostlist_auto->hostlist); } } bool LoadAllHostLists() { if (!LoadHostLists(¶ms.hostlists)) return false; MakeAutolistsNonEmpty(); return true; } static bool SearchHostList(strpool *hostlist, const char *host) { if (hostlist) { const char *p = host; bool bInHostList; while (p) { bInHostList = StrPoolCheckStr(hostlist, p); VPRINT("hostlist check for %s : %s\n", p, bInHostList ? "positive" : "negative"); if (bInHostList) return true; p = strchr(p, '.'); if (p) p++; } } return false; } static bool HostlistsReloadCheck(const struct hostlist_collection_head *hostlists) { struct hostlist_item *item; LIST_FOREACH(item, hostlists, next) { if (!LoadHostList(item->hfile)) return false; } MakeAutolistsNonEmpty(); return true; } bool HostlistsReloadCheckForProfile(const struct desync_profile *dp) { return HostlistsReloadCheck(&dp->hl_collection) && HostlistsReloadCheck(&dp->hl_collection_exclude); } // return : true = apply fooling, false = do not apply static bool HostlistCheck_(const struct hostlist_collection_head *hostlists, const struct hostlist_collection_head *hostlists_exclude, const char *host, bool *excluded, bool bSkipReloadCheck) { struct hostlist_item *item; if (excluded) *excluded = false; if (!bSkipReloadCheck) if (!HostlistsReloadCheck(hostlists) || !HostlistsReloadCheck(hostlists_exclude)) return false; LIST_FOREACH(item, hostlists_exclude, next) { VPRINT("[%s] exclude ", item->hfile->filename ? item->hfile->filename : "fixed"); if (SearchHostList(item->hfile->hostlist, host)) { if (excluded) *excluded = true; return false; } } // old behavior compat: all include lists are empty means check passes if (!hostlist_collection_is_empty(hostlists)) { LIST_FOREACH(item, hostlists, next) { VPRINT("[%s] include ", item->hfile->filename ? item->hfile->filename : "fixed"); if (SearchHostList(item->hfile->hostlist, host)) return true; } return false; } return true; } // return : true = apply fooling, false = do not apply bool HostlistCheck(const struct desync_profile *dp, const char *host, bool *excluded, bool bSkipReloadCheck) { VPRINT("* hostlist check for profile %d\n",dp->n); return HostlistCheck_(&dp->hl_collection, &dp->hl_collection_exclude, host, excluded, bSkipReloadCheck); } static struct hostlist_file *RegisterHostlist_(struct hostlist_files_head *hostlists, struct hostlist_collection_head *hl_collection, const char *filename) { struct hostlist_file *hfile; if (filename) { if (!(hfile=hostlist_files_search(hostlists, filename))) if (!(hfile=hostlist_files_add(hostlists, filename))) return NULL; if (!hostlist_collection_search(hl_collection, filename)) if (!hostlist_collection_add(hl_collection, hfile)) return NULL; } else { if (!(hfile=hostlist_files_add(hostlists, NULL))) return NULL; if (!hostlist_collection_add(hl_collection, hfile)) return NULL; } return hfile; } struct hostlist_file *RegisterHostlist(struct desync_profile *dp, bool bExclude, const char *filename) { if (filename && !file_mod_time(filename)) { DLOG_ERR("cannot access hostlist file '%s'\n",filename); return NULL; } return RegisterHostlist_( ¶ms.hostlists, bExclude ? &dp->hl_collection_exclude : &dp->hl_collection, filename); } void HostlistsDebug() { if (!params.debug) return; struct hostlist_file *hfile; struct desync_profile_list *dpl; struct hostlist_item *hl_item; LIST_FOREACH(hfile, ¶ms.hostlists, next) { if (hfile->filename) VPRINT("hostlist file %s%s\n",hfile->filename,hfile->hostlist ? "" : " (empty)"); else VPRINT("hostlist fixed%s\n",hfile->hostlist ? "" : " (empty)"); } LIST_FOREACH(dpl, ¶ms.desync_profiles, next) { LIST_FOREACH(hl_item, &dpl->dp.hl_collection, next) if (hl_item->hfile!=dpl->dp.hostlist_auto) { if (hl_item->hfile->filename) VPRINT("profile %d include hostlist %s%s\n",dpl->dp.n, hl_item->hfile->filename,hl_item->hfile->hostlist ? "" : " (empty)"); else VPRINT("profile %d include fixed hostlist%s\n",dpl->dp.n, hl_item->hfile->hostlist ? "" : " (empty)"); } LIST_FOREACH(hl_item, &dpl->dp.hl_collection_exclude, next) { if (hl_item->hfile->filename) VPRINT("profile %d exclude hostlist %s%s\n",dpl->dp.n,hl_item->hfile->filename,hl_item->hfile->hostlist ? "" : " (empty)"); else VPRINT("profile %d exclude fixed hostlist%s\n",dpl->dp.n,hl_item->hfile->hostlist ? "" : " (empty)"); } if (dpl->dp.hostlist_auto) VPRINT("profile %d auto hostlist %s%s\n",dpl->dp.n,dpl->dp.hostlist_auto->filename,dpl->dp.hostlist_auto->hostlist ? "" : " (empty)"); } }