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
33 CBC 465 : pg_check_dir(const char *dir)
34 : {
35 465 : int result = 1;
36 : DIR *chkdir;
37 : struct dirent *file;
38 465 : bool dot_found = false;
39 465 : bool mount_found = false;
40 : int readdir_errno;
41 :
42 465 : chkdir = opendir(dir);
43 465 : if (chkdir == NULL)
44 442 : return (errno == ENOENT) ? 0 : -1;
45 :
46 66 : while (errno = 0, (file = readdir(chkdir)) != NULL)
47 : {
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 "." */
56 4 : else if (file->d_name[0] == '.')
57 : {
58 UBC 0 : dot_found = true;
59 : }
60 : /* lost+found directory */
61 CBC 4 : else if (strcmp("lost+found", file->d_name) == 0)
62 : {
63 1 : mount_found = true;
64 : }
65 : #endif
66 : else
67 : {
68 3 : result = 4; /* not empty */
69 3 : break;
70 : }
71 : }
72 :
73 23 : if (errno)
74 UBC 0 : result = -1; /* some kind of I/O error? */
75 :
76 : /* Close chkdir and avoid overwriting the readdir errno on success */
77 CBC 23 : readdir_errno = errno;
78 23 : if (closedir(chkdir))
79 UBC 0 : result = -1; /* error executing closedir */
80 : else
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 */
88 23 : if (result == 1 && dot_found)
89 UBC 0 : result = 2;
90 :
91 CBC 23 : return result;
92 : }
|