]> granicus.if.org Git - postgresql/blob - src/port/pgcheckdir.c
Properly check for readdir/closedir() failures
[postgresql] / src / port / pgcheckdir.c
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-2014, 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 not empty
26  *              -1 if trouble accessing directory (errno reflects the error)
27  */
28 int
29 pg_check_dir(const char *dir)
30 {
31         int                     result = 1;
32         DIR                *chkdir;
33         struct dirent *file;
34         bool            dot_found = false;
35
36         chkdir = opendir(dir);
37         if (chkdir == NULL)
38                 return (errno == ENOENT) ? 0 : -1;
39
40         while (errno = 0, (file = readdir(chkdir)) != NULL)
41         {
42                 if (strcmp(".", file->d_name) == 0 ||
43                         strcmp("..", file->d_name) == 0)
44                 {
45                         /* skip this and parent directory */
46                         continue;
47                 }
48 #ifndef WIN32
49                 /* file starts with "." */
50                 else if (file->d_name[0] == '.')
51                 {
52                         dot_found = true;
53                 }
54                 else if (strcmp("lost+found", file->d_name) == 0)
55                 {
56                         result = 3;                     /* not empty, mount point */
57                         break;
58                 }
59 #endif
60                 else
61                 {
62                         result = 4;                     /* not empty */
63                         break;
64                 }
65         }
66
67 #ifdef WIN32
68         /* Bug in old Mingw dirent.c;  fixed in mingw-runtime-3.2, 2003-10-10 */
69         if (GetLastError() == ERROR_NO_MORE_FILES)
70                 errno = 0;
71 #endif
72
73         if (errno || closedir(chkdir))
74                 result = -1;                    /* some kind of I/O error? */
75
76         /* We report on dot-files if we _only_ find dot files */
77         if (result == 1 && dot_found)
78                 result = 2;
79
80         return result;
81 }