LCOV - differential code coverage report
Current view: top level - src/backend/libpq - be-secure-common.c (source / functions) Coverage Total Hit UNC UBC GBC GNC CBC DCB
Current: bed3ffbf9d952be6c7d739d068cdce44c046dfb7 vs 574581b50ac9c63dd9e4abebb731a3b67e5b50f6 Lines: 72.5 % 142 103 17 22 80 23 2
Current Date: 2026-05-05 10:23:31 +0900 Functions: 100.0 % 4 4 3 1 1
Baseline: lcov-20260505-025707-baseline Branches: 47.7 % 128 61 33 34 1 45 15
Baseline Date: 2026-05-05 10:27:06 +0900 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(30,360] days: 82.5 % 97 80 17 80
(360..) days: 51.1 % 45 23 22 23
Function coverage date bins:
(30,360] days: 100.0 % 3 3 3
(360..) days: 100.0 % 1 1 1
Branch coverage date bins:
(30,360] days: 57.7 % 78 45 33 45
(360..) days: 32.0 % 50 16 34 1 15

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * be-secure-common.c
                                  4                 :                :  *
                                  5                 :                :  * common implementation-independent SSL support code
                                  6                 :                :  *
                                  7                 :                :  * While be-secure.c contains the interfaces that the rest of the
                                  8                 :                :  * communications code calls, this file contains support routines that are
                                  9                 :                :  * used by the library-specific implementations such as be-secure-openssl.c.
                                 10                 :                :  *
                                 11                 :                :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
                                 12                 :                :  * Portions Copyright (c) 1994, Regents of the University of California
                                 13                 :                :  *
                                 14                 :                :  * IDENTIFICATION
                                 15                 :                :  *    src/backend/libpq/be-secure-common.c
                                 16                 :                :  *
                                 17                 :                :  *-------------------------------------------------------------------------
                                 18                 :                :  */
                                 19                 :                : 
                                 20                 :                : #include "postgres.h"
                                 21                 :                : 
                                 22                 :                : #include <sys/stat.h>
                                 23                 :                : #include <unistd.h>
                                 24                 :                : 
                                 25                 :                : #include "common/percentrepl.h"
                                 26                 :                : #include "common/string.h"
                                 27                 :                : #include "libpq/libpq.h"
                                 28                 :                : #include "storage/fd.h"
                                 29                 :                : #include "utils/builtins.h"
                                 30                 :                : #include "utils/guc.h"
                                 31                 :                : 
                                 32                 :                : static HostsLine *parse_hosts_line(TokenizedAuthLine *tok_line, int elevel);
                                 33                 :                : 
                                 34                 :                : /*
                                 35                 :                :  * Run ssl_passphrase_command
                                 36                 :                :  *
                                 37                 :                :  * prompt will be substituted for %p.  is_server_start determines the loglevel
                                 38                 :                :  * of error messages from executing the command, the loglevel for failures in
                                 39                 :                :  * param substitution will be ERROR regardless of is_server_start.  The actual
                                 40                 :                :  * command used depends on the configuration for the current host.
                                 41                 :                :  *
                                 42                 :                :  * The result will be put in buffer buf, which is of size size.  The return
                                 43                 :                :  * value is the length of the actual result.
                                 44                 :                :  */
                                 45                 :                : int
   48 dgustafsson@postgres       46                 :GNC          17 : run_ssl_passphrase_command(const char *cmd, const char *prompt,
                                 47                 :                :                            bool is_server_start, char *buf, int size)
                                 48                 :                : {
 2990 peter_e@gmx.net            49         [ +  + ]:CBC          17 :     int         loglevel = is_server_start ? ERROR : LOG;
                                 50                 :                :     char       *command;
                                 51                 :                :     FILE       *fh;
                                 52                 :                :     int         pclose_rc;
                                 53                 :             17 :     size_t      len = 0;
                                 54                 :                : 
                                 55         [ -  + ]:             17 :     Assert(prompt);
                                 56         [ -  + ]:             17 :     Assert(size > 0);
                                 57                 :             17 :     buf[0] = '\0';
                                 58                 :                : 
   48 dgustafsson@postgres       59                 :GNC          17 :     command = replace_percent_placeholders(cmd, "ssl_passphrase_command", "p", prompt);
                                 60                 :                : 
 1210 peter@eisentraut.org       61                 :CBC          17 :     fh = OpenPipeStream(command, "r");
 2990 peter_e@gmx.net            62         [ -  + ]:             17 :     if (fh == NULL)
                                 63                 :                :     {
 2990 peter_e@gmx.net            64         [ #  # ]:UBC           0 :         ereport(loglevel,
                                 65                 :                :                 (errcode_for_file_access(),
                                 66                 :                :                  errmsg("could not execute command \"%s\": %m",
                                 67                 :                :                         command)));
                                 68                 :              0 :         goto error;
                                 69                 :                :     }
                                 70                 :                : 
 2990 peter_e@gmx.net            71         [ -  + ]:CBC          17 :     if (!fgets(buf, size, fh))
                                 72                 :                :     {
 2990 peter_e@gmx.net            73         [ #  # ]:UBC           0 :         if (ferror(fh))
                                 74                 :                :         {
 2434 peter@eisentraut.org       75                 :              0 :             explicit_bzero(buf, size);
 2990 peter_e@gmx.net            76         [ #  # ]:              0 :             ereport(loglevel,
                                 77                 :                :                     (errcode_for_file_access(),
                                 78                 :                :                      errmsg("could not read from command \"%s\": %m",
                                 79                 :                :                             command)));
                                 80                 :              0 :             goto error;
                                 81                 :                :         }
                                 82                 :                :     }
                                 83                 :                : 
 2990 peter_e@gmx.net            84                 :CBC          17 :     pclose_rc = ClosePipeStream(fh);
                                 85         [ -  + ]:             17 :     if (pclose_rc == -1)
                                 86                 :                :     {
 2434 peter@eisentraut.org       87                 :UBC           0 :         explicit_bzero(buf, size);
 2990 peter_e@gmx.net            88         [ #  # ]:              0 :         ereport(loglevel,
                                 89                 :                :                 (errcode_for_file_access(),
                                 90                 :                :                  errmsg("could not close pipe to external command: %m")));
                                 91                 :              0 :         goto error;
                                 92                 :                :     }
 2990 peter_e@gmx.net            93         [ -  + ]:CBC          17 :     else if (pclose_rc != 0)
                                 94                 :                :     {
                                 95                 :                :         char       *reason;
                                 96                 :                : 
 2434 peter@eisentraut.org       97                 :UBC           0 :         explicit_bzero(buf, size);
  721 dgustafsson@postgres       98                 :              0 :         reason = wait_result_to_str(pclose_rc);
 2990 peter_e@gmx.net            99         [ #  # ]:              0 :         ereport(loglevel,
                                100                 :                :                 (errcode_for_file_access(),
                                101                 :                :                  errmsg("command \"%s\" failed",
                                102                 :                :                         command),
                                103                 :                :                  errdetail_internal("%s", reason)));
  721 dgustafsson@postgres      104                 :              0 :         pfree(reason);
 2990 peter_e@gmx.net           105                 :              0 :         goto error;
                                106                 :                :     }
                                107                 :                : 
                                108                 :                :     /* strip trailing newline and carriage return */
 2461 michael@paquier.xyz       109                 :CBC          17 :     len = pg_strip_crlf(buf);
                                110                 :                : 
 2990 peter_e@gmx.net           111                 :             17 : error:
 1210 peter@eisentraut.org      112                 :             17 :     pfree(command);
 2990 peter_e@gmx.net           113                 :             17 :     return len;
                                114                 :                : }
                                115                 :                : 
                                116                 :                : 
                                117                 :                : /*
                                118                 :                :  * Check permissions for SSL key files.
                                119                 :                :  */
                                120                 :                : bool
 2955                           121                 :             76 : check_ssl_key_file_permissions(const char *ssl_key_file, bool isServerStart)
                                122                 :                : {
                                123         [ +  + ]:             76 :     int         loglevel = isServerStart ? FATAL : LOG;
                                124                 :                :     struct stat buf;
                                125                 :                : 
                                126         [ -  + ]:             76 :     if (stat(ssl_key_file, &buf) != 0)
                                127                 :                :     {
 2955 peter_e@gmx.net           128         [ #  # ]:UBC           0 :         ereport(loglevel,
                                129                 :                :                 (errcode_for_file_access(),
                                130                 :                :                  errmsg("could not access private key file \"%s\": %m",
                                131                 :                :                         ssl_key_file)));
                                132                 :              0 :         return false;
                                133                 :                :     }
                                134                 :                : 
                                135                 :                :     /* Key file must be a regular file */
 2955 peter_e@gmx.net           136         [ -  + ]:CBC          76 :     if (!S_ISREG(buf.st_mode))
                                137                 :                :     {
 2955 peter_e@gmx.net           138         [ #  # ]:UBC           0 :         ereport(loglevel,
                                139                 :                :                 (errcode(ERRCODE_CONFIG_FILE_ERROR),
                                140                 :                :                  errmsg("private key file \"%s\" is not a regular file",
                                141                 :                :                         ssl_key_file)));
                                142                 :              0 :         return false;
                                143                 :                :     }
                                144                 :                : 
                                145                 :                :     /*
                                146                 :                :      * Refuse to load key files owned by users other than us or root, and
                                147                 :                :      * require no public access to the key file.  If the file is owned by us,
                                148                 :                :      * require mode 0600 or less.  If owned by root, require 0640 or less to
                                149                 :                :      * allow read access through either our gid or a supplementary gid that
                                150                 :                :      * allows us to read system-wide certificates.
                                151                 :                :      *
                                152                 :                :      * Note that roughly similar checks are performed in
                                153                 :                :      * src/interfaces/libpq/fe-secure-openssl.c so any changes here may need
                                154                 :                :      * to be made there as well.  The environment is different though; this
                                155                 :                :      * code can assume that we're not running as root.
                                156                 :                :      *
                                157                 :                :      * Ideally we would do similar permissions checks on Windows, but it is
                                158                 :                :      * not clear how that would work since Unix-style permissions may not be
                                159                 :                :      * available.
                                160                 :                :      */
                                161                 :                : #if !defined(WIN32) && !defined(__CYGWIN__)
 2955 peter_e@gmx.net           162   [ -  +  -  - ]:CBC          76 :     if (buf.st_uid != geteuid() && buf.st_uid != 0)
                                163                 :                :     {
 2955 peter_e@gmx.net           164         [ #  # ]:UBC           0 :         ereport(loglevel,
                                165                 :                :                 (errcode(ERRCODE_CONFIG_FILE_ERROR),
                                166                 :                :                  errmsg("private key file \"%s\" must be owned by the database user or root",
                                167                 :                :                         ssl_key_file)));
                                168                 :              0 :         return false;
                                169                 :                :     }
                                170                 :                : 
 2955 peter_e@gmx.net           171   [ +  -  +  - ]:CBC          76 :     if ((buf.st_uid == geteuid() && buf.st_mode & (S_IRWXG | S_IRWXO)) ||
                                172   [ -  +  -  - ]:             76 :         (buf.st_uid == 0 && buf.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO)))
                                173                 :                :     {
 2955 peter_e@gmx.net           174         [ #  # ]:UBC           0 :         ereport(loglevel,
                                175                 :                :                 (errcode(ERRCODE_CONFIG_FILE_ERROR),
                                176                 :                :                  errmsg("private key file \"%s\" has group or world access",
                                177                 :                :                         ssl_key_file),
                                178                 :                :                  errdetail("File must have permissions u=rw (0600) or less if owned by the database user, or permissions u=rw,g=r (0640) or less if owned by root.")));
                                179                 :              0 :         return false;
                                180                 :                :     }
                                181                 :                : #endif
                                182                 :                : 
 2955 peter_e@gmx.net           183                 :CBC          76 :     return true;
                                184                 :                : }
                                185                 :                : 
                                186                 :                : /*
                                187                 :                :  * parse_hosts_line
                                188                 :                :  *
                                189                 :                :  * Parses a loaded line from the pg_hosts.conf configuration and pulls out the
                                190                 :                :  * hostname, certificate, key and CA parts in order to build an SNI config in
                                191                 :                :  * the TLS backend. Validation of the parsed values is left for the TLS backend
                                192                 :                :  * to implement.
                                193                 :                :  */
                                194                 :                : static HostsLine *
   48 dgustafsson@postgres      195                 :GNC          37 : parse_hosts_line(TokenizedAuthLine *tok_line, int elevel)
                                196                 :                : {
                                197                 :                :     HostsLine  *parsedline;
                                198                 :                :     List       *tokens;
                                199                 :                :     ListCell   *field;
                                200                 :                :     AuthToken  *token;
                                201                 :                : 
                                202                 :             37 :     parsedline = palloc0(sizeof(HostsLine));
                                203                 :             37 :     parsedline->sourcefile = pstrdup(tok_line->file_name);
                                204                 :             37 :     parsedline->linenumber = tok_line->line_num;
                                205                 :             37 :     parsedline->rawline = pstrdup(tok_line->raw_line);
                                206                 :             37 :     parsedline->hostnames = NIL;
                                207                 :                : 
                                208                 :                :     /* Initialize optional fields */
                                209                 :             37 :     parsedline->ssl_passphrase_cmd = NULL;
                                210                 :             37 :     parsedline->ssl_passphrase_reload = false;
                                211                 :                : 
                                212                 :                :     /* Hostname */
                                213                 :             37 :     field = list_head(tok_line->fields);
                                214                 :             37 :     tokens = lfirst(field);
                                215   [ +  -  +  +  :            116 :     foreach_ptr(AuthToken, hostname, tokens)
                                              +  + ]
                                216                 :                :     {
                                217         [ +  + ]:             44 :         if ((tokens->length > 1) &&
                                218   [ +  +  -  + ]:             11 :             (strcmp(hostname->string, "*") == 0 || strcmp(hostname->string, "/no_sni/") == 0))
                                219                 :                :         {
                                220         [ +  - ]:              1 :             ereport(elevel,
                                221                 :                :                     errcode(ERRCODE_CONFIG_FILE_ERROR),
                                222                 :                :                     errmsg("default and non-SNI entries cannot be mixed with other entries"),
                                223                 :                :                     errcontext("line %d of configuration file \"%s\"",
                                224                 :                :                                tok_line->line_num, tok_line->file_name));
                                225                 :              1 :             return NULL;
                                226                 :                :         }
                                227                 :                : 
                                228                 :             43 :         parsedline->hostnames = lappend(parsedline->hostnames, pstrdup(hostname->string));
                                229                 :                :     }
                                230                 :                : 
                                231                 :                :     /* SSL Certificate (Required) */
                                232                 :             36 :     field = lnext(tok_line->fields, field);
                                233         [ -  + ]:             36 :     if (!field)
                                234                 :                :     {
   48 dgustafsson@postgres      235         [ #  # ]:UNC           0 :         ereport(elevel,
                                236                 :                :                 errcode(ERRCODE_CONFIG_FILE_ERROR),
                                237                 :                :                 errmsg("missing entry at end of line"),
                                238                 :                :                 errcontext("line %d of configuration file \"%s\"",
                                239                 :                :                            tok_line->line_num, tok_line->file_name));
                                240                 :              0 :         return NULL;
                                241                 :                :     }
   48 dgustafsson@postgres      242                 :GNC          36 :     tokens = lfirst(field);
                                243         [ -  + ]:             36 :     if (tokens->length > 1)
                                244                 :                :     {
   48 dgustafsson@postgres      245         [ #  # ]:UNC           0 :         ereport(elevel,
                                246                 :                :                 errcode(ERRCODE_CONFIG_FILE_ERROR),
                                247                 :                :                 errmsg("multiple values specified for SSL certificate"),
                                248                 :                :                 errcontext("line %d of configuration file \"%s\"",
                                249                 :                :                            tok_line->line_num, tok_line->file_name));
                                250                 :              0 :         return NULL;
                                251                 :                :     }
   48 dgustafsson@postgres      252                 :GNC          36 :     token = linitial(tokens);
                                253                 :             36 :     parsedline->ssl_cert = pstrdup(token->string);
                                254                 :                : 
                                255                 :                :     /* SSL key (Required) */
                                256                 :             36 :     field = lnext(tok_line->fields, field);
                                257         [ -  + ]:             36 :     if (!field)
                                258                 :                :     {
   48 dgustafsson@postgres      259         [ #  # ]:UNC           0 :         ereport(elevel,
                                260                 :                :                 errcode(ERRCODE_CONFIG_FILE_ERROR),
                                261                 :                :                 errmsg("missing entry at end of line"),
                                262                 :                :                 errcontext("line %d of configuration file \"%s\"",
                                263                 :                :                            tok_line->line_num, tok_line->file_name));
                                264                 :              0 :         return NULL;
                                265                 :                :     }
   48 dgustafsson@postgres      266                 :GNC          36 :     tokens = lfirst(field);
                                267         [ -  + ]:             36 :     if (tokens->length > 1)
                                268                 :                :     {
   48 dgustafsson@postgres      269         [ #  # ]:UNC           0 :         ereport(elevel,
                                270                 :                :                 errcode(ERRCODE_CONFIG_FILE_ERROR),
                                271                 :                :                 errmsg("multiple values specified for SSL key"),
                                272                 :                :                 errcontext("line %d of configuration file \"%s\"",
                                273                 :                :                            tok_line->line_num, tok_line->file_name));
                                274                 :              0 :         return NULL;
                                275                 :                :     }
   48 dgustafsson@postgres      276                 :GNC          36 :     token = linitial(tokens);
                                277                 :             36 :     parsedline->ssl_key = pstrdup(token->string);
                                278                 :                : 
                                279                 :                :     /* SSL CA (optional) */
                                280                 :             36 :     field = lnext(tok_line->fields, field);
                                281         [ +  + ]:             36 :     if (!field)
                                282                 :             14 :         return parsedline;
                                283                 :             22 :     tokens = lfirst(field);
                                284         [ -  + ]:             22 :     if (tokens->length > 1)
                                285                 :                :     {
   48 dgustafsson@postgres      286         [ #  # ]:UNC           0 :         ereport(elevel,
                                287                 :                :                 errcode(ERRCODE_CONFIG_FILE_ERROR),
                                288                 :                :                 errmsg("multiple values specified for SSL CA"),
                                289                 :                :                 errcontext("line %d of configuration file \"%s\"",
                                290                 :                :                            tok_line->line_num, tok_line->file_name));
                                291                 :              0 :         return NULL;
                                292                 :                :     }
   48 dgustafsson@postgres      293                 :GNC          22 :     token = linitial(tokens);
                                294                 :             22 :     parsedline->ssl_ca = pstrdup(token->string);
                                295                 :                : 
                                296                 :                :     /* SSL Passphrase Command (optional) */
                                297                 :             22 :     field = lnext(tok_line->fields, field);
                                298         [ +  + ]:             22 :     if (field)
                                299                 :                :     {
                                300                 :             12 :         tokens = lfirst(field);
                                301         [ -  + ]:             12 :         if (tokens->length > 1)
                                302                 :                :         {
   48 dgustafsson@postgres      303         [ #  # ]:UNC           0 :             ereport(elevel,
                                304                 :                :                     errcode(ERRCODE_CONFIG_FILE_ERROR),
                                305                 :                :                     errmsg("multiple values specified for SSL passphrase command"),
                                306                 :                :                     errcontext("line %d of configuration file \"%s\"",
                                307                 :                :                                tok_line->line_num, tok_line->file_name));
                                308                 :              0 :             return NULL;
                                309                 :                :         }
   48 dgustafsson@postgres      310                 :GNC          12 :         token = linitial(tokens);
                                311                 :             12 :         parsedline->ssl_passphrase_cmd = pstrdup(token->string);
                                312                 :                : 
                                313                 :                :         /*
                                314                 :                :          * SSL Passphrase Command support reload (optional). This field is
                                315                 :                :          * only supported if there was a passphrase command parsed first, so
                                316                 :                :          * nest it under the previous token.
                                317                 :                :          */
                                318                 :             12 :         field = lnext(tok_line->fields, field);
                                319         [ +  - ]:             12 :         if (field)
                                320                 :                :         {
                                321                 :             12 :             tokens = lfirst(field);
                                322                 :             12 :             token = linitial(tokens);
                                323                 :                : 
                                324                 :                :             /*
                                325                 :                :              * There should be no more tokens after this, if there are break
                                326                 :                :              * parsing and report error to avoid silently accepting incorrect
                                327                 :                :              * config.
                                328                 :                :              */
                                329         [ +  + ]:             12 :             if (lnext(tok_line->fields, field))
                                330                 :                :             {
                                331         [ +  - ]:              1 :                 ereport(elevel,
                                332                 :                :                         errcode(ERRCODE_CONFIG_FILE_ERROR),
                                333                 :                :                         errmsg("extra fields at end of line"),
                                334                 :                :                         errcontext("line %d of configuration file \"%s\"",
                                335                 :                :                                    tok_line->line_num, tok_line->file_name));
                                336                 :              1 :                 return NULL;
                                337                 :                :             }
                                338                 :                : 
                                339   [ +  -  +  + ]:             11 :             if (tokens->length > 1 || !parse_bool(token->string, &parsedline->ssl_passphrase_reload))
                                340                 :                :             {
                                341         [ +  - ]:              1 :                 ereport(elevel,
                                342                 :                :                         errcode(ERRCODE_CONFIG_FILE_ERROR),
                                343                 :                :                         errmsg("incorrect syntax for boolean value SSL_passphrase_cmd_reload"),
                                344                 :                :                         errcontext("line %d of configuration file \"%s\"",
                                345                 :                :                                    tok_line->line_num, tok_line->file_name));
                                346                 :              1 :                 return NULL;
                                347                 :                :             }
                                348                 :                :         }
                                349                 :                :     }
                                350                 :                : 
                                351                 :             20 :     return parsedline;
                                352                 :                : }
                                353                 :                : 
                                354                 :                : /*
                                355                 :                :  * load_hosts
                                356                 :                :  *
                                357                 :                :  * Reads and parses the pg_hosts.conf configuration file and passes back a List
                                358                 :                :  * of HostsLine elements containing the parsed lines, or NIL in case of an empty
                                359                 :                :  * file.  The list is returned in the hosts parameter. The function will return
                                360                 :                :  * a HostsFileLoadResult value detailing the result of the operation.  When
                                361                 :                :  * the hosts configuration failed to load, the err_msg variable may have more
                                362                 :                :  * information in case it was passed as non-NULL.
                                363                 :                :  */
                                364                 :                : HostsFileLoadResult
                                365                 :             25 : load_hosts(List **hosts, char **err_msg)
                                366                 :                : {
                                367                 :                :     FILE       *file;
                                368                 :                :     ListCell   *line;
                                369                 :             25 :     List       *hosts_lines = NIL;
                                370                 :             25 :     List       *parsed_lines = NIL;
                                371                 :                :     HostsLine  *newline;
                                372                 :             25 :     bool        ok = true;
                                373                 :                : 
                                374                 :                :     /*
                                375                 :                :      * If we cannot return results then error out immediately. This implies
                                376                 :                :      * API misuse or a similar kind of programmer error.
                                377                 :                :      */
                                378         [ -  + ]:             25 :     if (!hosts)
                                379                 :                :     {
   48 dgustafsson@postgres      380         [ #  # ]:UNC           0 :         if (err_msg)
                                381                 :              0 :             *err_msg = psprintf("cannot load config from \"%s\", return variable missing",
                                382                 :                :                                 HostsFileName);
                                383                 :              0 :         return HOSTSFILE_LOAD_FAILED;
                                384                 :                :     }
   48 dgustafsson@postgres      385                 :GNC          25 :     *hosts = NIL;
                                386                 :                : 
                                387                 :                :     /*
                                388                 :                :      * This is not an auth file per se, but it is using the same file format
                                389                 :                :      * as the pg_hba and pg_ident files and thus the same code infrastructure.
                                390                 :                :      * A future TODO might be to rename the supporting code with a more
                                391                 :                :      * generic name?
                                392                 :                :      */
                                393                 :             25 :     file = open_auth_file(HostsFileName, LOG, 0, err_msg);
                                394         [ +  + ]:             25 :     if (file == NULL)
                                395                 :                :     {
                                396         [ +  - ]:              1 :         if (errno == ENOENT)
                                397                 :              1 :             return HOSTSFILE_MISSING;
                                398                 :                : 
   48 dgustafsson@postgres      399                 :UNC           0 :         return HOSTSFILE_LOAD_FAILED;
                                400                 :                :     }
                                401                 :                : 
   48 dgustafsson@postgres      402                 :GNC          24 :     tokenize_auth_file(HostsFileName, file, &hosts_lines, LOG, 0);
                                403                 :                : 
                                404   [ +  -  +  +  :             61 :     foreach(line, hosts_lines)
                                              +  + ]
                                405                 :                :     {
                                406                 :             37 :         TokenizedAuthLine *tok_line = (TokenizedAuthLine *) lfirst(line);
                                407                 :                : 
                                408                 :                :         /*
                                409                 :                :          * Mark processing as not-ok in case lines are found with errors in
                                410                 :                :          * tokenization (.err_msg is set) or during parsing.
                                411                 :                :          */
                                412   [ +  -  +  + ]:             74 :         if ((tok_line->err_msg != NULL) ||
                                413                 :             37 :             ((newline = parse_hosts_line(tok_line, LOG)) == NULL))
                                414                 :                :         {
                                415                 :              3 :             ok = false;
                                416                 :              3 :             continue;
                                417                 :                :         }
                                418                 :                : 
                                419                 :             34 :         parsed_lines = lappend(parsed_lines, newline);
                                420                 :                :     }
                                421                 :                : 
                                422                 :                :     /* Free memory from tokenizer */
                                423                 :             24 :     free_auth_file(file, 0);
                                424                 :             24 :     *hosts = parsed_lines;
                                425                 :                : 
                                426         [ +  + ]:             24 :     if (!ok)
                                427                 :                :     {
                                428         [ +  - ]:              3 :         if (err_msg)
                                429                 :              3 :             *err_msg = psprintf("loading config from \"%s\" failed due to parsing error",
                                430                 :                :                                 HostsFileName);
                                431                 :              3 :         return HOSTSFILE_LOAD_FAILED;
                                432                 :                :     }
                                433                 :                : 
                                434         [ -  + ]:             21 :     if (parsed_lines == NIL)
   48 dgustafsson@postgres      435                 :UNC           0 :         return HOSTSFILE_EMPTY;
                                436                 :                : 
   48 dgustafsson@postgres      437                 :GNC          21 :     return HOSTSFILE_LOAD_OK;
                                438                 :                : }
        

Generated by: LCOV version 2.5.0-beta