aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/utils/misc/Makefile1
-rw-r--r--src/backend/utils/misc/conffiles.c164
-rw-r--r--src/backend/utils/misc/guc-file.l157
-rw-r--r--src/backend/utils/misc/meson.build1
-rw-r--r--src/include/utils/conffiles.h23
5 files changed, 204 insertions, 142 deletions
diff --git a/src/backend/utils/misc/Makefile b/src/backend/utils/misc/Makefile
index 60973090331..b9ee4eb48a5 100644
--- a/src/backend/utils/misc/Makefile
+++ b/src/backend/utils/misc/Makefile
@@ -15,6 +15,7 @@ include $(top_builddir)/src/Makefile.global
override CPPFLAGS := -I. -I$(srcdir) $(CPPFLAGS)
OBJS = \
+ conffiles.o \
guc.o \
guc-file.o \
guc_funcs.o \
diff --git a/src/backend/utils/misc/conffiles.c b/src/backend/utils/misc/conffiles.c
new file mode 100644
index 00000000000..4a99a1961e3
--- /dev/null
+++ b/src/backend/utils/misc/conffiles.c
@@ -0,0 +1,164 @@
+/*--------------------------------------------------------------------
+ * conffiles.c
+ *
+ * Utilities related to the handling of configuration files.
+ *
+ * This file contains some generic tools to work on configuration files
+ * used by PostgreSQL, be they related to GUCs or authentication.
+ *
+ *
+ * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/backend/utils/misc/conffiles.c
+ *
+ *--------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include <dirent.h>
+
+#include "common/file_utils.h"
+#include "miscadmin.h"
+#include "storage/fd.h"
+#include "utils/conffiles.h"
+
+/*
+ * AbsoluteConfigLocation
+ *
+ * Given a configuration file or directory location that may be a relative
+ * path, return an absolute one. We consider the location to be relative to
+ * the directory holding the calling file, or to DataDir if no calling file.
+ */
+char *
+AbsoluteConfigLocation(const char *location, const char *calling_file)
+{
+ char abs_path[MAXPGPATH];
+
+ if (is_absolute_path(location))
+ return pstrdup(location);
+ else
+ {
+ if (calling_file != NULL)
+ {
+ strlcpy(abs_path, calling_file, sizeof(abs_path));
+ get_parent_directory(abs_path);
+ join_path_components(abs_path, abs_path, location);
+ canonicalize_path(abs_path);
+ }
+ else
+ {
+ Assert(DataDir);
+ join_path_components(abs_path, DataDir, location);
+ canonicalize_path(abs_path);
+ }
+ return pstrdup(abs_path);
+ }
+}
+
+
+/*
+ * GetConfFilesInDir
+ *
+ * Returns the list of config files located in a directory, in alphabetical
+ * order. On error, returns NULL with details about the error stored in
+ * "err_msg".
+ */
+char **
+GetConfFilesInDir(const char *includedir, const char *calling_file,
+ int elevel, int *num_filenames, char **err_msg)
+{
+ char *directory;
+ DIR *d;
+ struct dirent *de;
+ char **filenames = NULL;
+ int size_filenames;
+
+ /*
+ * Reject directory name that is all-blank (including empty), as that
+ * leads to confusion --- we'd read the containing directory, typically
+ * resulting in recursive inclusion of the same file(s).
+ */
+ if (strspn(includedir, " \t\r\n") == strlen(includedir))
+ {
+ ereport(elevel,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("empty configuration directory name: \"%s\"",
+ includedir)));
+ *err_msg = "empty configuration directory name";
+ return NULL;
+ }
+
+ directory = AbsoluteConfigLocation(includedir, calling_file);
+ d = AllocateDir(directory);
+ if (d == NULL)
+ {
+ ereport(elevel,
+ (errcode_for_file_access(),
+ errmsg("could not open configuration directory \"%s\": %m",
+ directory)));
+ *err_msg = psprintf("could not open directory \"%s\"", directory);
+ goto cleanup;
+ }
+
+ /*
+ * Read the directory and put the filenames in an array, so we can sort
+ * them prior to caller processing the contents.
+ */
+ size_filenames = 32;
+ filenames = (char **) palloc(size_filenames * sizeof(char *));
+ *num_filenames = 0;
+
+ while ((de = ReadDir(d, directory)) != NULL)
+ {
+ PGFileType de_type;
+ char filename[MAXPGPATH];
+
+ /*
+ * Only parse files with names ending in ".conf". Explicitly reject
+ * files starting with ".". This excludes things like "." and "..",
+ * as well as typical hidden files, backup files, and editor debris.
+ */
+ if (strlen(de->d_name) < 6)
+ continue;
+ if (de->d_name[0] == '.')
+ continue;
+ if (strcmp(de->d_name + strlen(de->d_name) - 5, ".conf") != 0)
+ continue;
+
+ join_path_components(filename, directory, de->d_name);
+ canonicalize_path(filename);
+ de_type = get_dirent_type(filename, de, true, elevel);
+ if (de_type == PGFILETYPE_ERROR)
+ {
+ *err_msg = psprintf("could not stat file \"%s\"", filename);
+ pfree(filenames);
+ filenames = NULL;
+ goto cleanup;
+ }
+ else if (de_type != PGFILETYPE_DIR)
+ {
+ /* Add file to array, increasing its size in blocks of 32 */
+ if (*num_filenames >= size_filenames)
+ {
+ size_filenames += 32;
+ filenames = (char **) repalloc(filenames,
+ size_filenames * sizeof(char *));
+ }
+ filenames[*num_filenames] = pstrdup(filename);
+ (*num_filenames)++;
+ }
+ }
+
+ /* Sort the files by name before leaving */
+ if (*num_filenames > 0)
+ qsort(filenames, *num_filenames, sizeof(char *), pg_qsort_strcmp);
+
+cleanup:
+ if (d)
+ FreeDir(d);
+ pfree(directory);
+ return filenames;
+}
diff --git a/src/backend/utils/misc/guc-file.l b/src/backend/utils/misc/guc-file.l
index 2aa48ec9697..88245475d1c 100644
--- a/src/backend/utils/misc/guc-file.l
+++ b/src/backend/utils/misc/guc-file.l
@@ -17,6 +17,7 @@
#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "storage/fd.h"
+#include "utils/conffiles.h"
#include "utils/memutils.h"
}
@@ -156,37 +157,6 @@ ProcessConfigFile(GucContext context)
}
/*
- * Given a configuration file or directory location that may be a relative
- * path, return an absolute one. We consider the location to be relative to
- * the directory holding the calling file, or to DataDir if no calling file.
- */
-static char *
-AbsoluteConfigLocation(const char *location, const char *calling_file)
-{
- char abs_path[MAXPGPATH];
-
- if (is_absolute_path(location))
- return pstrdup(location);
- else
- {
- if (calling_file != NULL)
- {
- strlcpy(abs_path, calling_file, sizeof(abs_path));
- get_parent_directory(abs_path);
- join_path_components(abs_path, abs_path, location);
- canonicalize_path(abs_path);
- }
- else
- {
- Assert(DataDir);
- join_path_components(abs_path, DataDir, location);
- canonicalize_path(abs_path);
- }
- return pstrdup(abs_path);
- }
-}
-
-/*
* Read and parse a single configuration file. This function recurses
* to handle "include" directives.
*
@@ -605,127 +575,30 @@ ParseConfigDirectory(const char *includedir,
ConfigVariable **head_p,
ConfigVariable **tail_p)
{
- char *directory;
- DIR *d;
- struct dirent *de;
+ char *err_msg;
char **filenames;
int num_filenames;
- int size_filenames;
- bool status;
-
- /*
- * Reject directory name that is all-blank (including empty), as that
- * leads to confusion --- we'd read the containing directory, typically
- * resulting in recursive inclusion of the same file(s).
- */
- if (strspn(includedir, " \t\r\n") == strlen(includedir))
- {
- ereport(elevel,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("empty configuration directory name: \"%s\"",
- includedir)));
- record_config_file_error("empty configuration directory name",
- calling_file, calling_lineno,
- head_p, tail_p);
- return false;
- }
-
- /*
- * We don't check for recursion or too-deep nesting depth here; the
- * subsequent calls to ParseConfigFile will take care of that.
- */
-
- directory = AbsoluteConfigLocation(includedir, calling_file);
- d = AllocateDir(directory);
- if (d == NULL)
- {
- ereport(elevel,
- (errcode_for_file_access(),
- errmsg("could not open configuration directory \"%s\": %m",
- directory)));
- record_config_file_error(psprintf("could not open directory \"%s\"",
- directory),
- calling_file, calling_lineno,
- head_p, tail_p);
- status = false;
- goto cleanup;
- }
- /*
- * Read the directory and put the filenames in an array, so we can sort
- * them prior to processing the contents.
- */
- size_filenames = 32;
- filenames = (char **) palloc(size_filenames * sizeof(char *));
- num_filenames = 0;
+ filenames = GetConfFilesInDir(includedir, calling_file, elevel,
+ &num_filenames, &err_msg);
- while ((de = ReadDir(d, directory)) != NULL)
+ if (!filenames)
{
- PGFileType de_type;
- char filename[MAXPGPATH];
-
- /*
- * Only parse files with names ending in ".conf". Explicitly reject
- * files starting with ".". This excludes things like "." and "..",
- * as well as typical hidden files, backup files, and editor debris.
- */
- if (strlen(de->d_name) < 6)
- continue;
- if (de->d_name[0] == '.')
- continue;
- if (strcmp(de->d_name + strlen(de->d_name) - 5, ".conf") != 0)
- continue;
-
- join_path_components(filename, directory, de->d_name);
- canonicalize_path(filename);
- de_type = get_dirent_type(filename, de, true, elevel);
- if (de_type == PGFILETYPE_ERROR)
- {
- record_config_file_error(psprintf("could not stat file \"%s\"",
- filename),
- calling_file, calling_lineno,
- head_p, tail_p);
- status = false;
- goto cleanup;
- }
- else if (de_type != PGFILETYPE_DIR)
- {
- /* Add file to array, increasing its size in blocks of 32 */
- if (num_filenames >= size_filenames)
- {
- size_filenames += 32;
- filenames = (char **) repalloc(filenames,
- size_filenames * sizeof(char *));
- }
- filenames[num_filenames] = pstrdup(filename);
- num_filenames++;
- }
+ record_config_file_error(err_msg, calling_file, calling_lineno, head_p,
+ tail_p);
+ return false;
}
- if (num_filenames > 0)
+ for (int i = 0; i < num_filenames; i++)
{
- int i;
-
- qsort(filenames, num_filenames, sizeof(char *), pg_qsort_strcmp);
- for (i = 0; i < num_filenames; i++)
- {
- if (!ParseConfigFile(filenames[i], true,
- calling_file, calling_lineno,
- depth, elevel,
- head_p, tail_p))
- {
- status = false;
- goto cleanup;
- }
- }
+ if (!ParseConfigFile(filenames[i], true,
+ calling_file, calling_lineno,
+ depth, elevel,
+ head_p, tail_p))
+ return false;
}
- status = true;
-cleanup:
- if (d)
- FreeDir(d);
- pfree(directory);
- return status;
+ return true;
}
/*
diff --git a/src/backend/utils/misc/meson.build b/src/backend/utils/misc/meson.build
index db4de225e18..e7a9730229d 100644
--- a/src/backend/utils/misc/meson.build
+++ b/src/backend/utils/misc/meson.build
@@ -1,4 +1,5 @@
backend_sources += files(
+ 'conffiles.c',
'guc.c',
'guc_funcs.c',
'guc_tables.c',
diff --git a/src/include/utils/conffiles.h b/src/include/utils/conffiles.h
new file mode 100644
index 00000000000..3f23a2a011b
--- /dev/null
+++ b/src/include/utils/conffiles.h
@@ -0,0 +1,23 @@
+/*--------------------------------------------------------------------
+ * conffiles.h
+ *
+ * Utilities related to configuration files.
+ *
+ * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/conffiles.h
+ *
+ *--------------------------------------------------------------------
+ */
+#ifndef CONFFILES_H
+#define CONFFILES_H
+
+extern char *AbsoluteConfigLocation(const char *location,
+ const char *calling_file);
+extern char **GetConfFilesInDir(const char *includedir,
+ const char *calling_file,
+ int elevel, int *num_filenames,
+ char **err_msg);
+
+#endif /* CONFFILES_H */