Line data Source code
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-2017, 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 1 : pg_check_dir(const char *dir)
32 : {
33 1 : int result = 1;
34 : DIR *chkdir;
35 : struct dirent *file;
36 1 : bool dot_found = false;
37 1 : bool mount_found = false;
38 : int readdir_errno;
39 :
40 1 : chkdir = opendir(dir);
41 1 : if (chkdir == NULL)
42 1 : return (errno == ENOENT) ? 0 : -1;
43 :
44 0 : while (errno = 0, (file = readdir(chkdir)) != NULL)
45 : {
46 0 : if (strcmp(".", file->d_name) == 0 ||
47 0 : strcmp("..", file->d_name) == 0)
48 : {
49 : /* skip this and parent directory */
50 0 : continue;
51 : }
52 : #ifndef WIN32
53 : /* file starts with "." */
54 0 : else if (file->d_name[0] == '.')
55 : {
56 0 : dot_found = true;
57 : }
58 : /* lost+found directory */
59 0 : else if (strcmp("lost+found", file->d_name) == 0)
60 : {
61 0 : mount_found = true;
62 : }
63 : #endif
64 : else
65 : {
66 0 : result = 4; /* not empty */
67 0 : break;
68 : }
69 : }
70 :
71 0 : if (errno)
72 0 : result = -1; /* some kind of I/O error? */
73 :
74 : /* Close chkdir and avoid overwriting the readdir errno on success */
75 0 : readdir_errno = errno;
76 0 : if (closedir(chkdir))
77 0 : result = -1; /* error executing closedir */
78 : else
79 0 : errno = readdir_errno;
80 :
81 : /* We report on mount point if we find a lost+found directory */
82 0 : if (result == 1 && mount_found)
83 0 : result = 3;
84 :
85 : /* We report on dot-files if we _only_ find dot files */
86 0 : if (result == 1 && dot_found)
87 0 : result = 2;
88 :
89 0 : return result;
90 : }
|