PostgreSQL Source Code  git master
conffiles.c
Go to the documentation of this file.
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 AbsoluteConfigLocation(const char *location, const char *calling_file)
37 {
38  if (is_absolute_path(location))
39  return pstrdup(location);
40  else
41  {
42  char abs_path[MAXPGPATH];
43 
44  if (calling_file != NULL)
45  {
46  strlcpy(abs_path, calling_file, sizeof(abs_path));
47  get_parent_directory(abs_path);
48  join_path_components(abs_path, abs_path, location);
49  canonicalize_path(abs_path);
50  }
51  else
52  {
53  Assert(DataDir);
54  join_path_components(abs_path, DataDir, location);
55  canonicalize_path(abs_path);
56  }
57  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 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  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  if (strspn(includedir, " \t\r\n") == strlen(includedir))
85  {
86  ereport(elevel,
87  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
88  errmsg("empty configuration directory name: \"%s\"",
89  includedir)));
90  *err_msg = "empty configuration directory name";
91  return NULL;
92  }
93 
94  directory = AbsoluteConfigLocation(includedir, calling_file);
96  if (d == NULL)
97  {
98  ereport(elevel,
100  errmsg("could not open configuration directory \"%s\": %m",
101  directory)));
102  *err_msg = psprintf("could not open directory \"%s\"", directory);
103  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  size_filenames = 32;
111  filenames = (char **) palloc(size_filenames * sizeof(char *));
112  *num_filenames = 0;
113 
114  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  if (strlen(de->d_name) < 6)
125  continue;
126  if (de->d_name[0] == '.')
127  continue;
128  if (strcmp(de->d_name + strlen(de->d_name) - 5, ".conf") != 0)
129  continue;
130 
133  de_type = get_dirent_type(filename, de, true, elevel);
134  if (de_type == PGFILETYPE_ERROR)
135  {
136  *err_msg = psprintf("could not stat file \"%s\"", filename);
137  pfree(filenames);
138  filenames = NULL;
139  goto cleanup;
140  }
141  else if (de_type != PGFILETYPE_DIR)
142  {
143  /* Add file to array, increasing its size in blocks of 32 */
144  if (*num_filenames >= size_filenames)
145  {
146  size_filenames += 32;
147  filenames = (char **) repalloc(filenames,
148  size_filenames * sizeof(char *));
149  }
150  filenames[*num_filenames] = pstrdup(filename);
151  (*num_filenames)++;
152  }
153  }
154 
155  /* Sort the files by name before leaving */
156  if (*num_filenames > 0)
157  qsort(filenames, *num_filenames, sizeof(char *), pg_qsort_strcmp);
158 
159 cleanup:
160  if (d)
161  FreeDir(d);
162  pfree(directory);
163  return filenames;
164 }
static void cleanup(void)
Definition: bootstrap.c:696
char * AbsoluteConfigLocation(const char *location, const char *calling_file)
Definition: conffiles.c:36
char ** GetConfFilesInDir(const char *includedir, const char *calling_file, int elevel, int *num_filenames, char **err_msg)
Definition: conffiles.c:70
int errcode_for_file_access(void)
Definition: elog.c:881
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define ereport(elevel,...)
Definition: elog.h:149
struct dirent * ReadDir(DIR *dir, const char *dirname)
Definition: fd.c:2709
int FreeDir(DIR *dir)
Definition: fd.c:2761
DIR * AllocateDir(const char *dirname)
Definition: fd.c:2643
PGFileType get_dirent_type(const char *path, const struct dirent *de, bool look_through_symlinks, int elevel)
Definition: file_utils.c:406
PGFileType
Definition: file_utils.h:19
@ PGFILETYPE_DIR
Definition: file_utils.h:23
@ PGFILETYPE_ERROR
Definition: file_utils.h:20
char * DataDir
Definition: globals.c:66
Assert(fmt[strlen(fmt) - 1] !='\n')
char * pstrdup(const char *in)
Definition: mcxt.c:1624
void pfree(void *pointer)
Definition: mcxt.c:1436
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1456
void * palloc(Size size)
Definition: mcxt.c:1210
#define MAXPGPATH
static char * filename
Definition: pg_dumpall.c:119
void join_path_components(char *ret_path, const char *head, const char *tail)
Definition: path.c:219
#define is_absolute_path(filename)
Definition: port.h:103
void canonicalize_path(char *path)
Definition: path.c:264
int pg_qsort_strcmp(const void *a, const void *b)
Definition: qsort.c:19
void get_parent_directory(char *path)
Definition: path.c:977
#define qsort(a, b, c, d)
Definition: port.h:445
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
Definition: dirent.c:26
Definition: dirent.h:10
char d_name[MAX_PATH]
Definition: dirent.h:15
static const char * directory
Definition: zic.c:634