I forgot to free the memory allocated at 'filename = calloc' (why valgrind didn't warn...). Forget this patch. I will send another one tomorow.
Sorry Le 9 mai 2016 11:28 PM, "Maxime de Roucy" <[email protected]> a écrit : > If -f argument is a directory add all the files (and only files) it > containes to the config files list. > These files are added in lexical order (man alphasort). > The -f order is still respected: > > $ tree rootdir > rootdir > ├── root1 > ├── root2 > ├── root3 > ├── superdir1 > │ ├── aaa1 > │ ├── aaa2 > │ ├── aaa3 > │ ├── bbb1 -> aaa1 > │ └── wrong > │ └── wrongfile > └── superdir2 > ├── ccc1 > └── wronglink -> . > > $ ./haproxy -C rootdir -f root2 -f superdir2 \ > -f root3 -f superdir1 -f root1 > root2 > superdir2/ccc1 > root3 > superdir1/aaa1 > superdir1/aaa2 > superdir1/aaa3 > superdir1/bbb1 > root1 > > This can be useful on systemd where you can't change the haproxy > commande line options on service reload. > --- > doc/haproxy.1 | 8 +++-- > doc/management.txt | 23 ++++++------ > src/haproxy.c | 103 > ++++++++++++++++++++++++++++++++++++++++++++++++++--- > 3 files changed, 116 insertions(+), 18 deletions(-) > > diff --git a/doc/haproxy.1 b/doc/haproxy.1 > index a836d5d..6017efa 100644 > --- a/doc/haproxy.1 > +++ b/doc/haproxy.1 > @@ -6,7 +6,7 @@ HAProxy \- fast and reliable http reverse proxy and load > balancer > > .SH SYNOPSIS > > -haproxy \-f <configuration\ file> [\-L\ <name>] [\-n\ maxconn] [\-N\ > maxconn] [\-C\ <dir>] [\-v|\-vv] [\-d] [\-D] [\-q] [\-V] [\-c] [\-p\ > <pidfile>] [\-dk] [\-ds] [\-de] [\-dp] [\-db] [\-dM[<byte>]] [\-m\ <megs>] > [{\-sf|\-st}\ pidlist...] > +haproxy \-f <configuration\ file|dir> [\-L\ <name>] [\-n\ maxconn] [\-N\ > maxconn] [\-C\ <dir>] [\-v|\-vv] [\-d] [\-D] [\-q] [\-V] [\-c] [\-p\ > <pidfile>] [\-dk] [\-ds] [\-de] [\-dp] [\-db] [\-dM[<byte>]] [\-m\ <megs>] > [{\-sf|\-st}\ pidlist...] > > .SH DESCRIPTION > > @@ -33,8 +33,10 @@ instances without risking the system's stability. > .SH OPTIONS > > .TP > -\fB\-f <configuration file>\fP > -Specify configuration file path. > +\fB\-f <configuration file|dir>\fP > +Specify configuration file or directory path. If the argument is a > directory > +the files (and only files) it containes are added in lexical order (man > +alphasort). > > .TP > \fB\-L <name>\fP > diff --git a/doc/management.txt b/doc/management.txt > index e0469aa..3e51d49 100644 > --- a/doc/management.txt > +++ b/doc/management.txt > @@ -134,16 +134,19 @@ list of options is : > one of "global", "defaults", "peers", "listen", "frontend", > "backend", and > so on. A file cannot contain just a server list for example. > > - -f <cfgfile> : adds <cfgfile> to the list of configuration files to be > - loaded. Configuration files are loaded and processed in their > declaration > - order. This option may be specified multiple times to load multiple > files. > - See also "--". The difference between "--" and "-f" is that one "-f" > must > - be placed before each file name, while a single "--" is needed before > all > - file names. Both options can be used together, the command line > ordering > - still applies. When more than one file is specified, each file must > start > - on a section boundary, so the first keyword of each file must be one > of > - "global", "defaults", "peers", "listen", "frontend", "backend", and so > - on. A file cannot contain just a server list for example. > + -f <cfgfile|cfgdir> : adds <cfgfile> to the list of configuration files > to be > + loaded. If <cfgdir> is a directory, all the files (and only files) it > + containes are added in lexical order (man alphasort) to the list of > + configuration files to be loaded. Configuration files are loaded and > + processed in their declaration order. This option may be specified > multiple > + times to load multiple files. See also "--". The difference between > "--" > + and "-f" is that one "-f" must be placed before each file name, while > a > + single "--" is needed before all file names. Both options can be used > + together, the command line ordering still applies. When more than one > file > + is specified, each file must start on a section boundary, so the first > + keyword of each file must be one of "global", "defaults", "peers", > + "listen", "frontend", "backend", and so on. A file cannot contain > just a > + server list for example. > > -C <dir> : changes to directory <dir> before loading configuration > files. This is useful when using relative paths. Warning when using > diff --git a/src/haproxy.c b/src/haproxy.c > index 0c223e5..9824b7c 100644 > --- a/src/haproxy.c > +++ b/src/haproxy.c > @@ -33,10 +33,12 @@ > #include <ctype.h> > #include <sys/time.h> > #include <sys/types.h> > +#include <sys/stat.h> > #include <sys/socket.h> > #include <netinet/tcp.h> > #include <netinet/in.h> > #include <arpa/inet.h> > +#include <dirent.h> > #include <netdb.h> > #include <fcntl.h> > #include <errno.h> > @@ -423,7 +425,7 @@ void usage(char *name) > { > display_version(); > fprintf(stderr, > - "Usage : %s [-f <cfgfile>]* [ -vdV" > + "Usage : %s [-f <cfgfile|cfgdir>]* [ -vdV" > "D ] [ -n <maxconn> ] [ -N <maxpconn> ]\n" > " [ -p <pidfile> ] [ -m <max megs> ] [ -C <dir> ] > [-- <cfgfile>*]\n" > " -v displays version ; -vv shows known build > options.\n" > @@ -551,6 +553,94 @@ void dump(struct sig_handler *sh) > pool_gc2(); > } > > +/* This function check if cfg_cfgfiles containes directories. > + * If it find one, it add all the files (and only files) it containes > + * in cfg_cfgfiles in place of the directory (and remove the directory). > + * It add the files in lexical order. > + */ > +void cfgfiles_expand_directories(void) > +{ > + struct wordlist *wl, *wlb; > + > + list_for_each_entry_safe(wl, wlb, &cfg_cfgfiles, list) { > + struct stat file_stat; > + struct dirent **dir_entries; > + int dir_entries_nb; > + int dir_entries_it; > + > + if (stat(wl->s, &file_stat)) { > + Alert("Cannot open configuration file/directory %s > : %s\n", > + wl->s, > + strerror(errno)); > + exit(1); > + } > + > + if (!S_ISDIR(file_stat.st_mode)) > + continue; > + > + dir_entries_nb = scandir(wl->s, &dir_entries, NULL, > alphasort); > + if (dir_entries_nb < 0) { > + Alert("Cannot open configuration directory %s : > %s\n", > + wl->s, > + strerror(errno)); > + exit(1); > + } > + > + for (dir_entries_it = 0; dir_entries_it < dir_entries_nb; > dir_entries_it++) { > + struct dirent *dir_entry = > dir_entries[dir_entries_it]; > + char *filename; > + int filename_size = strlen(wl->s) > + + 1 /* for '/' */ > + + strlen(dir_entry->d_name); > + > + filename = calloc(filename_size + 1 /* for \0 */, > sizeof(*filename)); > + if (!filename) { > + Alert("Cannot load configuration files %s > : out of memory.\n", > + filename); > + exit(1); > + } > + > + sprintf(filename, "%s/%s", wl->s, > dir_entry->d_name); > + > + if (stat(filename, &file_stat)) { > + Alert("Cannot open configuration file %s : > %s\n", > + wl->s, > + strerror(errno)); > + exit(1); > + } > + > + /* don't add anything else than regular file in > cfg_cfgfiles > + * this way we avoid loops > + */ > + if (S_ISREG(file_stat.st_mode)) { > + struct wordlist *wlt; > + char *tmp_str; > + > + wlt = calloc(1, sizeof(*wlt)); > + tmp_str = strdup(filename); > + if (!wlt || !tmp_str) { > + Alert("Cannot load configuration > files %s : out of memory.\n", > + filename); > + exit(1); > + } > + > + wlt->s = tmp_str; > + > + /* add wlt (a file) before wl (a directory) > + * in cfg_cfgfiles > + */ > + LIST_ADDQ(&wl->list, &wlt->list); > + } > + free(dir_entry); > + } > + free(dir_entries); > + > + /* remove the current directory (wl) from cfg_cfgfiles */ > + LIST_DEL(&wl->list); > + free(wl); > + } > +} > + > /* > * This function initializes all the necessary variables. It only returns > * if everything is OK. If something fails, it exits. > @@ -738,7 +828,7 @@ void init(int argc, char **argv) > case 'f' : > wl = calloc(1, sizeof(*wl)); > if (!wl) { > - Alert("Cannot load > configuration file %s : out of memory.\n", *argv); > + Alert("Cannot load > configuration file/directory %s : out of memory.\n", *argv); > exit(1); > } > wl->s = *argv; > @@ -758,14 +848,17 @@ void init(int argc, char **argv) > (arg_mode & (MODE_DAEMON | MODE_SYSTEMD | MODE_FOREGROUND > | MODE_VERBOSE > | MODE_QUIET | MODE_CHECK | MODE_DEBUG)); > > - if (LIST_ISEMPTY(&cfg_cfgfiles)) > - usage(progname); > - > if (change_dir && chdir(change_dir) < 0) { > Alert("Could not change to directory %s : %s\n", > change_dir, strerror(errno)); > exit(1); > } > > + /* handle cfgfiles that are actualy directories */ > + cfgfiles_expand_directories(); > + > + if (LIST_ISEMPTY(&cfg_cfgfiles)) > + usage(progname); > + > global.maxsock = 10; /* reserve 10 fds ; will be incremented by > socket eaters */ > > init_default_instance(); > -- > 2.8.2 > >

