1
0
mirror of https://github.com/postgres/postgres.git synced 2025-08-18 12:22:09 +03:00
Files
postgres/src/port/pgcheckdir.c
Robert Haas 9a90ec9cff Improve pg_check_dir code and comments.
Avoid losing errno if readdir() fails and closedir() works.  Consistently
return 4 rather than 3 if both a lost+found directory and other files are
found, rather than returning one value or the other depending on the
order of the directory listing.  Update comments to match the actual
behavior.

These oversights date to commits 6f03927fce
and 17f1523932.

Marco Nenciarini
2015-02-17 10:54:29 -05:00

97 lines
2.1 KiB
C

/*-------------------------------------------------------------------------
*
* src/port/pgcheckdir.c
*
* A simple subroutine to check whether a directory exists and is empty or not.
* Useful in both initdb and the backend.
*
* Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*-------------------------------------------------------------------------
*/
#include "c.h"
#include <dirent.h>
/*
* Test to see if a directory exists and is empty or not.
*
* Returns:
* 0 if nonexistent
* 1 if exists and empty
* 2 if exists and contains _only_ dot files
* 3 if exists and contains a mount point
* 4 if exists and not empty
* -1 if trouble accessing directory (errno reflects the error)
*/
int
pg_check_dir(const char *dir)
{
int result = 1;
DIR *chkdir;
struct dirent *file;
bool dot_found = false;
bool mount_found = false;
int readdir_errno;
chkdir = opendir(dir);
if (chkdir == NULL)
return (errno == ENOENT) ? 0 : -1;
while (errno = 0, (file = readdir(chkdir)) != NULL)
{
if (strcmp(".", file->d_name) == 0 ||
strcmp("..", file->d_name) == 0)
{
/* skip this and parent directory */
continue;
}
#ifndef WIN32
/* file starts with "." */
else if (file->d_name[0] == '.')
{
dot_found = true;
}
/* lost+found directory */
else if (strcmp("lost+found", file->d_name) == 0)
{
mount_found = true;
}
#endif
else
{
result = 4; /* not empty */
break;
}
}
#ifdef WIN32
/* Bug in old Mingw dirent.c; fixed in mingw-runtime-3.2, 2003-10-10 */
if (GetLastError() == ERROR_NO_MORE_FILES)
errno = 0;
#endif
if (errno)
result = -1; /* some kind of I/O error? */
/* Close chkdir and avoid overwriting the readdir errno on success */
readdir_errno = errno;
if (closedir(chkdir))
result = -1; /* error executing closedir */
else
errno = readdir_errno;
/* We report on mount point if we find a lost+found directory */
if (result == 1 && mount_found)
result = 3;
/* We report on dot-files if we _only_ find dot files */
if (result == 1 && dot_found)
result = 2;
return result;
}