Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
// 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;
}
Ejemplo n.º 3
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;
	}
}