Warn about initdb using mount-points
authorBruce Momjian <bruce@momjian.us>
Sat, 16 Feb 2013 23:52:50 +0000 (18:52 -0500)
committerBruce Momjian <bruce@momjian.us>
Sat, 16 Feb 2013 23:52:50 +0000 (18:52 -0500)
Add code to detect and warn about trying to initdb or create pg_xlog on
mount points.

src/bin/initdb/initdb.c
src/bin/pg_basebackup/pg_basebackup.c
src/port/pgcheckdir.c

index 2ea3f6ed02bebb7d2040fd7769b0db52b23f98fa..b8faf9cba6a391cbfdb56daef3b54198f7ff9b0a 100644 (file)
@@ -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)
 {
index b6f774469b1b4ef42a5b2ee55073127fd948fa71..fb5a1bd1c199035b4d75295aa63b8743960926f0 100644 (file)
@@ -371,6 +371,8 @@ verify_dir_is_empty_or_create(char *dirname)
             */
            return;
        case 2:
+       case 3:
+       case 4:
 
            /*
             * Exists, not empty
index 3b8258c0353429814d118a4a239f9225eda70854..aee59975afcc9d22480f5c0c7c8c05703bca35f0 100644 (file)
@@ -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;
 }