| /*------------------------------------------------------------------------- |
| * |
| * 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-2021, 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; |
| } |
| } |
| |
| 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; |
| } |