summaryrefslogtreecommitdiffstats
path: root/src/port/pgcheckdir.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/port/pgcheckdir.c')
-rw-r--r--src/port/pgcheckdir.c92
1 files changed, 92 insertions, 0 deletions
diff --git a/src/port/pgcheckdir.c b/src/port/pgcheckdir.c
new file mode 100644
index 0000000..6c09cf2
--- /dev/null
+++ b/src/port/pgcheckdir.c
@@ -0,0 +1,92 @@
+/*-------------------------------------------------------------------------
+ *
+ * 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-2022, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/port/pgcheckdir.c
+ *-------------------------------------------------------------------------
+ */
+
+#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;
+ }
+ }
+
+ 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;
+}