LCOV - code coverage report
Current view: top level - src/backend/utils/misc - conffiles.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 74.1 % 54 40
Test Date: 2026-07-26 06:15:43 Functions: 100.0 % 2 2
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 60.0 % 30 18

             Branch data     Line data    Source code
       1                 :             : /*--------------------------------------------------------------------
       2                 :             :  * conffiles.c
       3                 :             :  *
       4                 :             :  * Utilities related to the handling of configuration files.
       5                 :             :  *
       6                 :             :  * This file contains some generic tools to work on configuration files
       7                 :             :  * used by PostgreSQL, be they related to GUCs or authentication.
       8                 :             :  *
       9                 :             :  *
      10                 :             :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
      11                 :             :  * Portions Copyright (c) 1994, Regents of the University of California
      12                 :             :  *
      13                 :             :  * IDENTIFICATION
      14                 :             :  *    src/backend/utils/misc/conffiles.c
      15                 :             :  *
      16                 :             :  *--------------------------------------------------------------------
      17                 :             :  */
      18                 :             : 
      19                 :             : #include "postgres.h"
      20                 :             : 
      21                 :             : #include <dirent.h>
      22                 :             : 
      23                 :             : #include "common/file_utils.h"
      24                 :             : #include "miscadmin.h"
      25                 :             : #include "storage/fd.h"
      26                 :             : #include "utils/conffiles.h"
      27                 :             : 
      28                 :             : /*
      29                 :             :  * AbsoluteConfigLocation
      30                 :             :  *
      31                 :             :  * Given a configuration file or directory location that may be a relative
      32                 :             :  * path, return an absolute one.  We consider the location to be relative to
      33                 :             :  * the directory holding the calling file, or to DataDir if no calling file.
      34                 :             :  */
      35                 :             : char *
      36                 :        5770 : AbsoluteConfigLocation(const char *location, const char *calling_file)
      37                 :             : {
      38         [ +  + ]:        5770 :     if (is_absolute_path(location))
      39                 :        3410 :         return pstrdup(location);
      40                 :             :     else
      41                 :             :     {
      42                 :             :         char        abs_path[MAXPGPATH];
      43                 :             : 
      44         [ +  + ]:        2360 :         if (calling_file != NULL)
      45                 :             :         {
      46                 :         230 :             strlcpy(abs_path, calling_file, sizeof(abs_path));
      47                 :         230 :             get_parent_directory(abs_path);
      48                 :         230 :             join_path_components(abs_path, abs_path, location);
      49                 :         230 :             canonicalize_path(abs_path);
      50                 :             :         }
      51                 :             :         else
      52                 :             :         {
      53                 :             :             Assert(DataDir);
      54                 :        2130 :             join_path_components(abs_path, DataDir, location);
      55                 :        2130 :             canonicalize_path(abs_path);
      56                 :             :         }
      57                 :        2360 :         return pstrdup(abs_path);
      58                 :             :     }
      59                 :             : }
      60                 :             : 
      61                 :             : 
      62                 :             : /*
      63                 :             :  * GetConfFilesInDir
      64                 :             :  *
      65                 :             :  * Returns the list of config files located in a directory, in alphabetical
      66                 :             :  * order.  On error, returns NULL with details about the error stored in
      67                 :             :  * "err_msg".
      68                 :             :  */
      69                 :             : char      **
      70                 :           4 : GetConfFilesInDir(const char *includedir, const char *calling_file,
      71                 :             :                   int elevel, int *num_filenames, char **err_msg)
      72                 :             : {
      73                 :             :     char       *directory;
      74                 :             :     DIR        *d;
      75                 :             :     struct dirent *de;
      76                 :           4 :     char      **filenames = NULL;
      77                 :             :     int         size_filenames;
      78                 :             : 
      79                 :             :     /*
      80                 :             :      * Reject directory name that is all-blank (including empty), as that
      81                 :             :      * leads to confusion --- we'd read the containing directory, typically
      82                 :             :      * resulting in recursive inclusion of the same file(s).
      83                 :             :      */
      84         [ -  + ]:           4 :     if (strspn(includedir, " \t\r\n") == strlen(includedir))
      85                 :             :     {
      86         [ #  # ]:           0 :         ereport(elevel,
      87                 :             :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
      88                 :             :                  errmsg("empty configuration directory name: \"%s\"",
      89                 :             :                         includedir)));
      90                 :           0 :         *err_msg = "empty configuration directory name";
      91                 :           0 :         return NULL;
      92                 :             :     }
      93                 :             : 
      94                 :           4 :     directory = AbsoluteConfigLocation(includedir, calling_file);
      95                 :           4 :     d = AllocateDir(directory);
      96         [ -  + ]:           4 :     if (d == NULL)
      97                 :             :     {
      98         [ #  # ]:           0 :         ereport(elevel,
      99                 :             :                 (errcode_for_file_access(),
     100                 :             :                  errmsg("could not open configuration directory \"%s\": %m",
     101                 :             :                         directory)));
     102                 :           0 :         *err_msg = psprintf("could not open directory \"%s\"", directory);
     103                 :           0 :         goto cleanup;
     104                 :             :     }
     105                 :             : 
     106                 :             :     /*
     107                 :             :      * Read the directory and put the filenames in an array, so we can sort
     108                 :             :      * them prior to caller processing the contents.
     109                 :             :      */
     110                 :           4 :     size_filenames = 32;
     111                 :           4 :     filenames = palloc_array(char *, size_filenames);
     112                 :           4 :     *num_filenames = 0;
     113                 :             : 
     114         [ +  + ]:          24 :     while ((de = ReadDir(d, directory)) != NULL)
     115                 :             :     {
     116                 :             :         PGFileType  de_type;
     117                 :             :         char        filename[MAXPGPATH];
     118                 :             : 
     119                 :             :         /*
     120                 :             :          * Only parse files with names ending in ".conf".  Explicitly reject
     121                 :             :          * files starting with ".".  This excludes things like "." and "..",
     122                 :             :          * as well as typical hidden files, backup files, and editor debris.
     123                 :             :          */
     124         [ +  + ]:          20 :         if (strlen(de->d_name) < 6)
     125                 :          12 :             continue;
     126         [ -  + ]:          12 :         if (de->d_name[0] == '.')
     127                 :           0 :             continue;
     128         [ +  + ]:          12 :         if (strcmp(de->d_name + strlen(de->d_name) - 5, ".conf") != 0)
     129                 :           4 :             continue;
     130                 :             : 
     131                 :           8 :         join_path_components(filename, directory, de->d_name);
     132                 :           8 :         canonicalize_path(filename);
     133                 :           8 :         de_type = get_dirent_type(filename, de, true, elevel);
     134         [ -  + ]:           8 :         if (de_type == PGFILETYPE_ERROR)
     135                 :             :         {
     136                 :           0 :             *err_msg = psprintf("could not stat file \"%s\"", filename);
     137                 :           0 :             pfree(filenames);
     138                 :           0 :             filenames = NULL;
     139                 :           0 :             goto cleanup;
     140                 :             :         }
     141         [ +  - ]:           8 :         else if (de_type != PGFILETYPE_DIR)
     142                 :             :         {
     143                 :             :             /* Add file to array, increasing its size in blocks of 32 */
     144         [ -  + ]:           8 :             if (*num_filenames >= size_filenames)
     145                 :             :             {
     146                 :           0 :                 size_filenames += 32;
     147                 :           0 :                 filenames = (char **) repalloc(filenames,
     148                 :             :                                                size_filenames * sizeof(char *));
     149                 :             :             }
     150                 :           8 :             filenames[*num_filenames] = pstrdup(filename);
     151                 :           8 :             (*num_filenames)++;
     152                 :             :         }
     153                 :             :     }
     154                 :             : 
     155                 :             :     /* Sort the files by name before leaving */
     156         [ -  + ]:           4 :     if (*num_filenames > 0)
     157                 :           4 :         qsort(filenames, *num_filenames, sizeof(char *), pg_qsort_strcmp);
     158                 :             : 
     159                 :           0 : cleanup:
     160         [ +  - ]:           4 :     if (d)
     161                 :           4 :         FreeDir(d);
     162                 :           4 :     pfree(directory);
     163                 :           4 :     return filenames;
     164                 :             : }
        

Generated by: LCOV version 2.0-1