mirror of https://github.com/postgres/postgres
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/Y2IgaH5YzIq2b+iR@paquier.xyzpull/108/head
parent
b0b72c64a0
commit
a1a7bb8f16
@ -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; |
||||
} |
||||
@ -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 */ |
||||
Loading…
Reference in new issue