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
>
>

Reply via email to