Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a1a7bb8

Browse files
committed
Move code related to configuration files in directories to new file
The code in charge of listing and classifying a set of configuration files in a directory was located in guc-file.l, being used currently for GUCs under "include_dir". This code is planned to be used for an upcoming feature able to include configuration files for ident and HBA files from a directory, similarly to GUCs. In both cases, the file names, suffixed by ".conf", have to be ordered alphabetically. This logic is moved to a new file, called conffiles.c, so as it is easier to share this facility between GUCs and the HBA/ident parsing logic. Author: Julien Rouhaud, Michael Paquier Discussion: https://postgr.es/m/[email protected]
1 parent b0b72c6 commit a1a7bb8

File tree

5 files changed

+204
-142
lines changed

5 files changed

+204
-142
lines changed

src/backend/utils/misc/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ include $(top_builddir)/src/Makefile.global
1515
override CPPFLAGS := -I. -I$(srcdir) $(CPPFLAGS)
1616

1717
OBJS = \
18+
conffiles.o \
1819
guc.o \
1920
guc-file.o \
2021
guc_funcs.o \

src/backend/utils/misc/conffiles.c

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
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-2022, 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+
char abs_path[MAXPGPATH];
39+
40+
if (is_absolute_path(location))
41+
return pstrdup(location);
42+
else
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);
95+
d = AllocateDir(directory);
96+
if (d == NULL)
97+
{
98+
ereport(elevel,
99+
(errcode_for_file_access(),
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+
131+
join_path_components(filename, directory, de->d_name);
132+
canonicalize_path(filename);
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+
}

src/backend/utils/misc/guc-file.l

Lines changed: 15 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "mb/pg_wchar.h"
1818
#include "miscadmin.h"
1919
#include "storage/fd.h"
20+
#include "utils/conffiles.h"
2021
#include "utils/memutils.h"
2122
}
2223

@@ -155,37 +156,6 @@ ProcessConfigFile(GucContext context)
155156
MemoryContextDelete(config_cxt);
156157
}
157158

158-
/*
159-
* Given a configuration file or directory location that may be a relative
160-
* path, return an absolute one. We consider the location to be relative to
161-
* the directory holding the calling file, or to DataDir if no calling file.
162-
*/
163-
static char *
164-
AbsoluteConfigLocation(const char *location, const char *calling_file)
165-
{
166-
char abs_path[MAXPGPATH];
167-
168-
if (is_absolute_path(location))
169-
return pstrdup(location);
170-
else
171-
{
172-
if (calling_file != NULL)
173-
{
174-
strlcpy(abs_path, calling_file, sizeof(abs_path));
175-
get_parent_directory(abs_path);
176-
join_path_components(abs_path, abs_path, location);
177-
canonicalize_path(abs_path);
178-
}
179-
else
180-
{
181-
Assert(DataDir);
182-
join_path_components(abs_path, DataDir, location);
183-
canonicalize_path(abs_path);
184-
}
185-
return pstrdup(abs_path);
186-
}
187-
}
188-
189159
/*
190160
* Read and parse a single configuration file. This function recurses
191161
* to handle "include" directives.
@@ -605,127 +575,30 @@ ParseConfigDirectory(const char *includedir,
605575
ConfigVariable **head_p,
606576
ConfigVariable **tail_p)
607577
{
608-
char *directory;
609-
DIR *d;
610-
struct dirent *de;
578+
char *err_msg;
611579
char **filenames;
612580
int num_filenames;
613-
int size_filenames;
614-
bool status;
615-
616-
/*
617-
* Reject directory name that is all-blank (including empty), as that
618-
* leads to confusion --- we'd read the containing directory, typically
619-
* resulting in recursive inclusion of the same file(s).
620-
*/
621-
if (strspn(includedir, " \t\r\n") == strlen(includedir))
622-
{
623-
ereport(elevel,
624-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
625-
errmsg("empty configuration directory name: \"%s\"",
626-
includedir)));
627-
record_config_file_error("empty configuration directory name",
628-
calling_file, calling_lineno,
629-
head_p, tail_p);
630-
return false;
631-
}
632-
633-
/*
634-
* We don't check for recursion or too-deep nesting depth here; the
635-
* subsequent calls to ParseConfigFile will take care of that.
636-
*/
637-
638-
directory = AbsoluteConfigLocation(includedir, calling_file);
639-
d = AllocateDir(directory);
640-
if (d == NULL)
641-
{
642-
ereport(elevel,
643-
(errcode_for_file_access(),
644-
errmsg("could not open configuration directory \"%s\": %m",
645-
directory)));
646-
record_config_file_error(psprintf("could not open directory \"%s\"",
647-
directory),
648-
calling_file, calling_lineno,
649-
head_p, tail_p);
650-
status = false;
651-
goto cleanup;
652-
}
653581

654-
/*
655-
* Read the directory and put the filenames in an array, so we can sort
656-
* them prior to processing the contents.
657-
*/
658-
size_filenames = 32;
659-
filenames = (char **) palloc(size_filenames * sizeof(char *));
660-
num_filenames = 0;
582+
filenames = GetConfFilesInDir(includedir, calling_file, elevel,
583+
&num_filenames, &err_msg);
661584

662-
while ((de = ReadDir(d, directory)) != NULL)
585+
if (!filenames)
663586
{
664-
PGFileType de_type;
665-
char filename[MAXPGPATH];
666-
667-
/*
668-
* Only parse files with names ending in ".conf". Explicitly reject
669-
* files starting with ".". This excludes things like "." and "..",
670-
* as well as typical hidden files, backup files, and editor debris.
671-
*/
672-
if (strlen(de->d_name) < 6)
673-
continue;
674-
if (de->d_name[0] == '.')
675-
continue;
676-
if (strcmp(de->d_name + strlen(de->d_name) - 5, ".conf") != 0)
677-
continue;
678-
679-
join_path_components(filename, directory, de->d_name);
680-
canonicalize_path(filename);
681-
de_type = get_dirent_type(filename, de, true, elevel);
682-
if (de_type == PGFILETYPE_ERROR)
683-
{
684-
record_config_file_error(psprintf("could not stat file \"%s\"",
685-
filename),
686-
calling_file, calling_lineno,
687-
head_p, tail_p);
688-
status = false;
689-
goto cleanup;
690-
}
691-
else if (de_type != PGFILETYPE_DIR)
692-
{
693-
/* Add file to array, increasing its size in blocks of 32 */
694-
if (num_filenames >= size_filenames)
695-
{
696-
size_filenames += 32;
697-
filenames = (char **) repalloc(filenames,
698-
size_filenames * sizeof(char *));
699-
}
700-
filenames[num_filenames] = pstrdup(filename);
701-
num_filenames++;
702-
}
587+
record_config_file_error(err_msg, calling_file, calling_lineno, head_p,
588+
tail_p);
589+
return false;
703590
}
704591

705-
if (num_filenames > 0)
592+
for (int i = 0; i < num_filenames; i++)
706593
{
707-
int i;
708-
709-
qsort(filenames, num_filenames, sizeof(char *), pg_qsort_strcmp);
710-
for (i = 0; i < num_filenames; i++)
711-
{
712-
if (!ParseConfigFile(filenames[i], true,
713-
calling_file, calling_lineno,
714-
depth, elevel,
715-
head_p, tail_p))
716-
{
717-
status = false;
718-
goto cleanup;
719-
}
720-
}
594+
if (!ParseConfigFile(filenames[i], true,
595+
calling_file, calling_lineno,
596+
depth, elevel,
597+
head_p, tail_p))
598+
return false;
721599
}
722-
status = true;
723600

724-
cleanup:
725-
if (d)
726-
FreeDir(d);
727-
pfree(directory);
728-
return status;
601+
return true;
729602
}
730603

731604
/*

src/backend/utils/misc/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
backend_sources += files(
2+
'conffiles.c',
23
'guc.c',
34
'guc_funcs.c',
45
'guc_tables.c',

src/include/utils/conffiles.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*--------------------------------------------------------------------
2+
* conffiles.h
3+
*
4+
* Utilities related to configuration files.
5+
*
6+
* Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
7+
* Portions Copyright (c) 1994, Regents of the University of California
8+
*
9+
* src/include/utils/conffiles.h
10+
*
11+
*--------------------------------------------------------------------
12+
*/
13+
#ifndef CONFFILES_H
14+
#define CONFFILES_H
15+
16+
extern char *AbsoluteConfigLocation(const char *location,
17+
const char *calling_file);
18+
extern char **GetConfFilesInDir(const char *includedir,
19+
const char *calling_file,
20+
int elevel, int *num_filenames,
21+
char **err_msg);
22+
23+
#endif /* CONFFILES_H */

0 commit comments

Comments
 (0)