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