LCOV - code coverage report
Current view: top level - src/backend/utils/misc - conffiles.c (source / functions) Hit Total Coverage
Test: PostgreSQL 17devel Lines: 40 54 74.1 %
Date: 2024-04-24 03:11:24 Functions: 2 2 100.0 %
Legend: Lines: hit not hit

          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-2024, 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        7118 : AbsoluteConfigLocation(const char *location, const char *calling_file)
      37             : {
      38        7118 :     if (is_absolute_path(location))
      39        4380 :         return pstrdup(location);
      40             :     else
      41             :     {
      42             :         char        abs_path[MAXPGPATH];
      43             : 
      44        2738 :         if (calling_file != NULL)
      45             :         {
      46         156 :             strlcpy(abs_path, calling_file, sizeof(abs_path));
      47         156 :             get_parent_directory(abs_path);
      48         156 :             join_path_components(abs_path, abs_path, location);
      49         156 :             canonicalize_path(abs_path);
      50             :         }
      51             :         else
      52             :         {
      53             :             Assert(DataDir);
      54        2582 :             join_path_components(abs_path, DataDir, location);
      55        2582 :             canonicalize_path(abs_path);
      56             :         }
      57        2738 :         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           8 : 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           8 :     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           8 :     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           8 :     directory = AbsoluteConfigLocation(includedir, calling_file);
      95           8 :     d = AllocateDir(directory);
      96           8 :     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           8 :     size_filenames = 32;
     111           8 :     filenames = (char **) palloc(size_filenames * sizeof(char *));
     112           8 :     *num_filenames = 0;
     113             : 
     114          48 :     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          40 :         if (strlen(de->d_name) < 6)
     125          24 :             continue;
     126          24 :         if (de->d_name[0] == '.')
     127           0 :             continue;
     128          24 :         if (strcmp(de->d_name + strlen(de->d_name) - 5, ".conf") != 0)
     129           8 :             continue;
     130             : 
     131          16 :         join_path_components(filename, directory, de->d_name);
     132          16 :         canonicalize_path(filename);
     133          16 :         de_type = get_dirent_type(filename, de, true, elevel);
     134          16 :         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          16 :         else if (de_type != PGFILETYPE_DIR)
     142             :         {
     143             :             /* Add file to array, increasing its size in blocks of 32 */
     144          16 :             if (*num_filenames >= size_filenames)
     145             :             {
     146           0 :                 size_filenames += 32;
     147           0 :                 filenames = (char **) repalloc(filenames,
     148             :                                                size_filenames * sizeof(char *));
     149             :             }
     150          16 :             filenames[*num_filenames] = pstrdup(filename);
     151          16 :             (*num_filenames)++;
     152             :         }
     153             :     }
     154             : 
     155             :     /* Sort the files by name before leaving */
     156           8 :     if (*num_filenames > 0)
     157           8 :         qsort(filenames, *num_filenames, sizeof(char *), pg_qsort_strcmp);
     158             : 
     159           0 : cleanup:
     160           8 :     if (d)
     161           8 :         FreeDir(d);
     162           8 :     pfree(directory);
     163           8 :     return filenames;
     164             : }

Generated by: LCOV version 1.14