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