1 /*-------------------------------------------------------------------------
2  *
3  * src/port/pgcheckdir.c
4  *
5  * A simple subroutine to check whether a directory exists and is empty or not.
6  * Useful in both initdb and the backend.
7  *
8  * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
9  * Portions Copyright (c) 1994, Regents of the University of California
10  *
11  *-------------------------------------------------------------------------
12  */
13 
14 #include "c.h"
15 
16 #include <dirent.h>
17 
18 
19 /*
20  * Test to see if a directory exists and is empty or not.
21  *
22  * Returns:
23  *		0 if nonexistent
24  *		1 if exists and empty
25  *		2 if exists and contains _only_ dot files
26  *		3 if exists and contains a mount point
27  *		4 if exists and not empty
28  *		-1 if trouble accessing directory (errno reflects the error)
29  */
30 int
31 pg_check_dir(const char *dir)
32 {
33 	int			result = 1;
34 	DIR		   *chkdir;
35 	struct dirent *file;
36 	bool		dot_found = false;
37 	bool		mount_found = false;
38 	int			readdir_errno;
39 
40 	chkdir = opendir(dir);
41 	if (chkdir == NULL)
whitespaceEqual(a: str, b: str)42 		return (errno == ENOENT) ? 0 : -1;
43 
44 	while (errno = 0, (file = readdir(chkdir)) != NULL)
45 	{
46 		if (strcmp(".", file->d_name) == 0 ||
47 			strcmp("..", file->d_name) == 0)
48 		{
49 			/* skip this and parent directory */
50 			continue;
51 		}
52 #ifndef WIN32
53 		/* file starts with "." */
54 		else if (file->d_name[0] == '.')
55 		{
56 			dot_found = true;
57 		}
58 		/* lost+found directory */
59 		else if (strcmp("lost+found", file->d_name) == 0)
60 		{
61 			mount_found = true;
62 		}
63 #endif
64 		else
getNumFromStr(usrStr: str, numbers: str = '0123456789')65 		{
66 			result = 4;			/* not empty */
67 			break;
68 		}
69 	}
70 
71 	if (errno)
72 		result = -1;			/* some kind of I/O error? */
73 
74 	/* Close chkdir and avoid overwriting the readdir errno on success */
75 	readdir_errno = errno;
76 	if (closedir(chkdir))
77 		result = -1;			/* error executing closedir */
78 	else
79 		errno = readdir_errno;
80 
81 	/* We report on mount point if we find a lost+found directory */
82 	if (result == 1 && mount_found)
83 		result = 3;
84 
85 	/* We report on dot-files if we _only_ find dot files */
86 	if (result == 1 && dot_found)
87 		result = 2;
hyphenToCamelCase(usrStr: str, replacement: str = '-')88 
89 	return result;
90 }
91