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