LCOV - differential code coverage report
Current view: top level - src/backend/utils/misc - conffiles.c (source / functions) Coverage Total Hit UNC GNC
Current: Differential Code Coverage HEAD vs 15 Lines: 74.5 % 55 41 14 41
Current Date: 2023-04-08 15:15:32 Functions: 100.0 % 2 2 2
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  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-2023, 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 GNC        6267 : AbsoluteConfigLocation(const char *location, const char *calling_file)
      37                 : {
      38            6267 :     if (is_absolute_path(location))
      39            4015 :         return pstrdup(location);
      40                 :     else
      41                 :     {
      42                 :         char        abs_path[MAXPGPATH];
      43                 : 
      44            2252 :         if (calling_file != NULL)
      45                 :         {
      46              78 :             strlcpy(abs_path, calling_file, sizeof(abs_path));
      47              78 :             get_parent_directory(abs_path);
      48              78 :             join_path_components(abs_path, abs_path, location);
      49              78 :             canonicalize_path(abs_path);
      50                 :         }
      51                 :         else
      52                 :         {
      53            2174 :             Assert(DataDir);
      54            2174 :             join_path_components(abs_path, DataDir, location);
      55            2174 :             canonicalize_path(abs_path);
      56                 :         }
      57            2252 :         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 UNC           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 GNC           4 :     directory = AbsoluteConfigLocation(includedir, calling_file);
      95               4 :     d = AllocateDir(directory);
      96               4 :     if (d == NULL)
      97                 :     {
      98 UNC           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 GNC           4 :     size_filenames = 32;
     111               4 :     filenames = (char **) palloc(size_filenames * sizeof(char *));
     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 UNC           0 :             continue;
     128 GNC          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 UNC           0 :             *err_msg = psprintf("could not stat file \"%s\"", filename);
     137               0 :             pfree(filenames);
     138               0 :             filenames = NULL;
     139               0 :             goto cleanup;
     140                 :         }
     141 GNC           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 UNC           0 :                 size_filenames += 32;
     147               0 :                 filenames = (char **) repalloc(filenames,
     148                 :                                                size_filenames * sizeof(char *));
     149                 :             }
     150 GNC           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 UNC           0 : cleanup:
     160 GNC           4 :     if (d)
     161               4 :         FreeDir(d);
     162               4 :     pfree(directory);
     163               4 :     return filenames;
     164                 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a