static #endif int cstat_get_client_names(struct cstat **clist, const char *clientconfdir) { int i=0; int n=0; int ret=-1; struct cstat *c; struct cstat *cnew; struct dirent **dir=NULL; if(entries_in_directory_no_sort(clientconfdir, &dir, &n, 1 /*atime*/)) { logp("scandir failed for %s in %s: %s\n", clientconfdir, __func__, strerror(errno)); goto end; } for(i=0; i<n; i++) { // looks_like...() also avoids '.' and '..'. if(looks_like_tmp_or_hidden_file(dir[i]->d_name)) continue; for(c=*clist; c; c=c->next) { if(!c->name) continue; if(!strcmp(dir[i]->d_name, c->name)) break; } if(c) continue; // We do not have this client yet. Add it. if(!(cnew=cstat_alloc()) || cstat_init_with_cntr(cnew, dir[i]->d_name, clientconfdir)) goto end; cstat_add_to_list(clist, cnew); } ret=0; end: if(dir) { for(i=0; i<n; i++) free_v((void **)&dir[i]); free_v((void **)&dir); } return ret; }
static int get_client_names(struct cstat **clist, struct conf *conf) { int m=0; int n=-1; int ret=-1; struct cstat *c; struct cstat *cnew; struct dirent **dir=NULL; if((n=scandir(conf->clientconfdir, &dir, 0, 0))<0) { logp("could not scandir clientconfdir: %s\n", conf->clientconfdir, strerror(errno)); goto end; } for(m=0; m<n; m++) { if(dir[m]->d_ino==0 // looks_like...() also avoids '.' and '..'. || looks_like_tmp_or_hidden_file(dir[m]->d_name)) continue; for(c=*clist; c; c=c->next) { if(!c->name) continue; if(!strcmp(dir[m]->d_name, c->name)) break; } if(c) continue; // We do not have this client yet. Add it. if(!(cnew=cstat_alloc()) || cstat_init(cnew, dir[m]->d_name, conf->clientconfdir) || cstat_add_to_list(clist, cnew)) goto end; } ret=0; end: for(m=0; m<n; m++) free_v((void **)&dir[m]); free_v((void **)&dir); return ret; }
int conf_load_clientconfdir(struct conf **globalcs, struct conf **cconfs) { int ret=-1; char *path=NULL; const char *cname=NULL; if(conf_init_save_cname_and_version(cconfs)) goto end; cname=get_string(cconfs[OPT_CNAME]); if(looks_like_tmp_or_hidden_file(cname)) { logp("client name '%s' is invalid\n", cname); goto end; } if(!(path=prepend_s(get_string(globalcs[OPT_CLIENTCONFDIR]), cname))) goto end; ret=conf_load_overrides(globalcs, cconfs, path); end: free_w(&path); return ret; }
static int iterate_over_clients(struct conf **globalcs, struct strlist *grouplist, const char *ext, unsigned int maxlinks) { int ret=0; DIR *dirp=NULL; struct conf **cconfs=NULL; struct dirent *dirinfo=NULL; const char *globalclientconfdir=get_string(globalcs[OPT_CLIENTCONFDIR]); signal(SIGABRT, &sighandler); signal(SIGTERM, &sighandler); signal(SIGINT, &sighandler); if(!(cconfs=confs_alloc())) return -1; if(confs_init(cconfs)) return -1; if(!(dirp=opendir(globalclientconfdir))) { logp("Could not opendir '%s': %s\n", globalclientconfdir, strerror(errno)); return 0; } while((dirinfo=readdir(dirp))) { char *lockfile=NULL; char *lockfilebase=NULL; char *client_lockdir=NULL; struct lock *lock=NULL; if(dirinfo->d_ino==0 // looks_like...() also avoids '.' and '..'. || looks_like_tmp_or_hidden_file(dirinfo->d_name) || !is_regular_file(globalclientconfdir, dirinfo->d_name)) continue; confs_free_content(cconfs); if(confs_init(cconfs)) return -1; if(set_string(cconfs[OPT_CNAME], dirinfo->d_name)) return -1; if(conf_load_clientconfdir(globalcs, cconfs)) { logp("could not load config for client %s\n", dirinfo->d_name); return 0; } if(grouplist) { const char *dedup_group= get_string(cconfs[OPT_DEDUP_GROUP]); if(!dedup_group || !in_group(grouplist, dedup_group)) continue; } if(!(client_lockdir=get_string(cconfs[OPT_CLIENT_LOCKDIR]))) client_lockdir=get_string(cconfs[OPT_DIRECTORY]); if(!(lockfilebase=prepend(client_lockdir, dirinfo->d_name, "/")) || !(lockfile=prepend(lockfilebase, BEDUP_LOCKFILE_NAME, "/"))) { free_w(&lockfilebase); free_w(&lockfile); ret=-1; break; } free_w(&lockfilebase); if(!(lock=lock_alloc_and_init(lockfile))) { ret=-1; break; } lock_get(lock); free_w(&lockfile); if(lock->status!=GET_LOCK_GOT) { logp("Could not get %s\n", lock->path); continue; } logp("Got %s\n", lock->path); // Remember that we got that lock. lock_add_to_list(&locklist, lock); if(process_dir(get_string(cconfs[OPT_DIRECTORY]), dirinfo->d_name, ext, maxlinks, 1 /* burp mode */, 0 /* level */)) { ret=-1; break; } ccount++; } closedir(dirp); locks_release_and_free(&locklist); confs_free(&cconfs); return ret; }