mirror of
https://github.com/postgres/postgres.git
synced 2025-11-09 06:21:09 +03:00
Expand the use of get_dirent_type(), shaving a few calls to stat()/lstat()
Several backend-side loops scanning one or more directories with ReadDir() (WAL segment recycle/removal in xlog.c, backend-side directory copy, temporary file removal, configuration file parsing, some logical decoding logic and some pgtz stuff) already know the type of the entry being scanned thanks to the dirent structure associated to the entry, on platforms where we know about DT_REG, DT_DIR and DT_LNK to make the difference between a regular file, a directory and a symbolic link. Relying on the direct structure of an entry saves a few system calls to stat() and lstat() in the loops updated here, shaving some code while on it. The logic of the code remains the same, calling stat() or lstat() depending on if it is necessary to look through symlinks. Authors: Nathan Bossart, Bharath Rupireddy Reviewed-by: Andres Freund, Thomas Munro, Michael Paquier Discussion: https://postgr.es/m/CALj2ACV8n-J-f=yiLUOx2=HrQGPSOZM3nWzyQQvLPcccPXxEdg@mail.gmail.com
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "common/file_utils.h"
|
||||
#include "mb/pg_wchar.h"
|
||||
#include "miscadmin.h"
|
||||
#include "storage/fd.h"
|
||||
@@ -1017,7 +1018,7 @@ ParseConfigDirectory(const char *includedir,
|
||||
|
||||
while ((de = ReadDir(d, directory)) != NULL)
|
||||
{
|
||||
struct stat st;
|
||||
PGFileType de_type;
|
||||
char filename[MAXPGPATH];
|
||||
|
||||
/*
|
||||
@@ -1034,32 +1035,9 @@ ParseConfigDirectory(const char *includedir,
|
||||
|
||||
join_path_components(filename, directory, de->d_name);
|
||||
canonicalize_path(filename);
|
||||
if (stat(filename, &st) == 0)
|
||||
de_type = get_dirent_type(filename, de, true, elevel);
|
||||
if (de_type == PGFILETYPE_ERROR)
|
||||
{
|
||||
if (!S_ISDIR(st.st_mode))
|
||||
{
|
||||
/* 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++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* stat does not care about permissions, so the most likely reason
|
||||
* a file can't be accessed now is if it was removed between the
|
||||
* directory listing and now.
|
||||
*/
|
||||
ereport(elevel,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not stat file \"%s\": %m",
|
||||
filename)));
|
||||
record_config_file_error(psprintf("could not stat file \"%s\"",
|
||||
filename),
|
||||
calling_file, calling_lineno,
|
||||
@@ -1067,6 +1045,18 @@ ParseConfigDirectory(const char *includedir,
|
||||
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++;
|
||||
}
|
||||
}
|
||||
|
||||
if (num_filenames > 0)
|
||||
|
||||
Reference in New Issue
Block a user