static int reload_from_client_confs(struct cstat **clist, struct conf *conf) { struct cstat *c; static struct conf *cconf=NULL; if(!cconf && !(cconf=conf_alloc())) goto error; for(c=*clist; c; c=c->next) { // Look at the client conf files to see if they have changed, // and reload bits and pieces if they have. struct stat statp; if(!c->conffile) continue; if(stat(c->conffile, &statp) || !S_ISREG(statp.st_mode)) { cstat_remove(clist, &c); continue; } if(statp.st_mtime==c->conf_mtime) { // conf file has not changed - no need to do anything. continue; } c->conf_mtime=statp.st_mtime; conf_free_content(cconf); if(!(cconf->cname=strdup_w(c->name, __func__))) goto error; if(conf_set_client_global(conf, cconf) || conf_load(c->conffile, cconf, 0)) { cstat_remove(clist, &c); continue; } if(set_cstat_from_conf(c, cconf)) goto error; } return 0; error: conf_free(cconf); cconf=NULL; return -1; }
// This decides which directories to start backing up, and which // are subdirectories which don't need to be started separately. static int finalise_start_dirs(struct conf **c) { struct strlist *s=NULL; struct strlist *last_ie=NULL; struct strlist *last_sd=NULL; // Make sure that the startdir list starts empty, or chaos will ensue. conf_free_content(c[OPT_STARTDIR]); for(s=get_strlist(c[OPT_INCLUDE]); s; s=s->next) { #ifdef HAVE_WIN32 convert_backslashes(&s->path); #endif if(path_checks(s->path, "ERROR: Please use absolute include/exclude paths.\n")) return -1; // Ensure that we do not backup the same directory twice. if(last_ie && !strcmp(s->path, last_ie->path)) { logp("Directory appears twice in conf: %s\n", s->path); return -1; } // If it is not a subdirectory of the most recent start point, // we have found another start point. if(!get_strlist(c[OPT_STARTDIR]) || !last_sd || !is_subdir(last_sd->path, s->path)) { // Do not use strlist_add_sorted, because last_sd is // relying on incexcdir already being sorted. if(add_to_strlist(c[OPT_STARTDIR], s->path, s->flag)) return -1; last_sd=s; } else { // If it is not a starting directory, it should at // least be included as a cross_filesystem entry. if(add_to_cross_filesystem(c, s->path)) return -1; } last_ie=s; } return 0; }
static int process_incoming_client(int rfd, struct conf *conf, SSL_CTX *ctx, const char *conffile, int is_status_server) { int cfd=-1; pid_t childpid; int pipe_rfd[2]; int pipe_wfd[2]; socklen_t client_length=0; struct sockaddr_in client_name; client_length=sizeof(client_name); if((cfd=accept(rfd, (struct sockaddr *) &client_name, &client_length))==-1) { // Look out, accept will get interrupted by SIGCHLDs. if(errno==EINTR) return 0; logp("accept failed on %d: %s\n", rfd, strerror(errno)); return -1; } reuseaddr(cfd); chld_check_for_exiting(); if(!conf->forking) { if(is_status_server) return run_status_server(&rfd, &cfd, -1, conffile); else return run_child(&rfd, &cfd, ctx, conffile, conf->forking); } if(chld_add_incoming(conf, is_status_server)) { logp("Closing new connection.\n"); close_fd(&cfd); return 0; } if(pipe(pipe_rfd)<0 || pipe(pipe_wfd)<0) { logp("pipe failed: %s", strerror(errno)); close_fd(&cfd); return -1; } /* fork off our new process to handle this request */ switch((childpid=fork())) { case -1: logp("fork failed: %s\n", strerror(errno)); return -1; case 0: { int ret; // child struct sigaction sa; // Set SIGCHLD back to default, so that I // can get sensible returns from waitpid. memset(&sa, 0, sizeof(sa)); sa.sa_handler=SIG_DFL; sigaction(SIGCHLD, &sa, NULL); close(pipe_rfd[0]); // close read end close(pipe_wfd[1]); // close write end conf_free_content(conf); set_blocking(pipe_rfd[1]); status_wfd=pipe_rfd[1]; if(is_status_server) ret=run_status_server(&rfd, &cfd, pipe_wfd[0], conffile); else ret=run_child(&rfd, &cfd, ctx, conffile, conf->forking); close(pipe_rfd[1]); close(pipe_wfd[0]); exit(ret); } default: // parent close(pipe_rfd[1]); // close write end close(pipe_wfd[0]); // close read end // keep a note of the child pid. if(is_status_server) logp("forked status server child pid %d\n", childpid); else logp("forked child pid %d\n", childpid); chld_forked(childpid, pipe_rfd[0], pipe_wfd[1], is_status_server); close_fd(&cfd); return 0; } }