diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c index 2ea3f6ed02..b8faf9cba6 100644 --- a/src/bin/initdb/initdb.c +++ b/src/bin/initdb/initdb.c @@ -257,6 +257,7 @@ void setup_signals(void); void setup_text_search(void); void create_data_directory(void); void create_xlog_symlink(void); +void warn_on_mount_point(int error); void initialize_data_directory(void); @@ -3144,7 +3145,9 @@ setup_signals(void) void create_data_directory(void) { - switch (pg_check_dir(pg_data)) + int ret; + + switch ((ret = pg_check_dir(pg_data))) { case 0: /* PGDATA not there, must create it */ @@ -3179,15 +3182,20 @@ create_data_directory(void) break; case 2: + case 3: + case 4: /* Present and not empty */ fprintf(stderr, _("%s: directory \"%s\" exists but is not empty\n"), progname, pg_data); - fprintf(stderr, - _("If you want to create a new database system, either remove or empty\n" - "the directory \"%s\" or run %s\n" - "with an argument other than \"%s\".\n"), - pg_data, progname, pg_data); + if (ret != 4) + warn_on_mount_point(ret); + else + fprintf(stderr, + _("If you want to create a new database system, either remove or empty\n" + "the directory \"%s\" or run %s\n" + "with an argument other than \"%s\".\n"), + pg_data, progname, pg_data); exit(1); /* no further message needed */ default: @@ -3206,6 +3214,7 @@ create_xlog_symlink(void) if (strcmp(xlog_dir, "") != 0) { char *linkloc; + int ret; /* clean up xlog directory name, check it's absolute */ canonicalize_path(xlog_dir); @@ -3216,7 +3225,7 @@ create_xlog_symlink(void) } /* check if the specified xlog directory exists/is empty */ - switch (pg_check_dir(xlog_dir)) + switch ((ret = pg_check_dir(xlog_dir))) { case 0: /* xlog directory not there, must create it */ @@ -3255,14 +3264,19 @@ create_xlog_symlink(void) break; case 2: + case 3: + case 4: /* Present and not empty */ fprintf(stderr, _("%s: directory \"%s\" exists but is not empty\n"), progname, xlog_dir); - fprintf(stderr, - _("If you want to store the transaction log there, either\n" - "remove or empty the directory \"%s\".\n"), - xlog_dir); + if (ret != 4) + warn_on_mount_point(ret); + else + fprintf(stderr, + _("If you want to store the transaction log there, either\n" + "remove or empty the directory \"%s\".\n"), + xlog_dir); exit_nicely(); default: @@ -3291,6 +3305,21 @@ create_xlog_symlink(void) } +void +warn_on_mount_point(int error) +{ + if (error == 2) + fprintf(stderr, + _("It contains a dot-prefixed/invisible file, perhaps due to it being a mount point.\n")); + else if (error == 3) + fprintf(stderr, + _("It contains a lost+found directory, perhaps due to it being a mount point.\n")); + + fprintf(stderr, + _("Using the top-level directory of a mount point is not recommended.\n")); +} + + void initialize_data_directory(void) { diff --git a/src/bin/pg_basebackup/pg_basebackup.c b/src/bin/pg_basebackup/pg_basebackup.c index b6f774469b..fb5a1bd1c1 100644 --- a/src/bin/pg_basebackup/pg_basebackup.c +++ b/src/bin/pg_basebackup/pg_basebackup.c @@ -371,6 +371,8 @@ verify_dir_is_empty_or_create(char *dirname) */ return; case 2: + case 3: + case 4: /* * Exists, not empty diff --git a/src/port/pgcheckdir.c b/src/port/pgcheckdir.c index 3b8258c035..aee59975af 100644 --- a/src/port/pgcheckdir.c +++ b/src/port/pgcheckdir.c @@ -31,6 +31,7 @@ pg_check_dir(const char *dir) int result = 1; DIR *chkdir; struct dirent *file; + bool dot_found = false; errno = 0; @@ -47,15 +48,26 @@ pg_check_dir(const char *dir) /* skip this and parent directory */ continue; } +#ifndef WIN32 + /* file starts with "." */ + else if (file->d_name[0] == '.') + { + dot_found = true; + } + else if (strcmp("lost+found", file->d_name) == 0) + { + result = 3; /* not empty, mount point */ + break; + } +#endif else { - result = 2; /* not empty */ + result = 4; /* not empty */ break; } } #ifdef WIN32 - /* * This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in * released version @@ -69,5 +81,9 @@ pg_check_dir(const char *dir) if (errno != 0) result = -1; /* some kind of I/O error? */ + /* We report on dot-files if we _only_ find dot files */ + if (result == 1 && dot_found) + result = 2; + return result; }