/* read the control file */
        ControlFile = get_controlfile(DataDir, NULL);
+       if (!ControlFile)
+               ereport(ERROR,
+                               (errmsg("calculated CRC checksum does not match value stored in file")));
 
        values[0] = Int32GetDatum(ControlFile->pg_control_version);
        nulls[0] = false;
 
        /* Read the control file. */
        ControlFile = get_controlfile(DataDir, NULL);
+       if (!ControlFile)
+               ereport(ERROR,
+                               (errmsg("calculated CRC checksum does not match value stored in file")));
 
        /*
         * Calculate name of the WAL file containing the latest checkpoint's REDO
 
        /* read the control file */
        ControlFile = get_controlfile(DataDir, NULL);
+       if (!ControlFile)
+               ereport(ERROR,
+                               (errmsg("calculated CRC checksum does not match value stored in file")));
 
        values[0] = LSNGetDatum(ControlFile->minRecoveryPoint);
        nulls[0] = false;
 
        /* read the control file */
        ControlFile = get_controlfile(DataDir, NULL);
+       if (!ControlFile)
+               ereport(ERROR,
+                               (errmsg("calculated CRC checksum does not match value stored in file")));
 
        values[0] = Int32GetDatum(ControlFile->maxAlign);
        nulls[0] = false;
 
 
 #include "postgres_fe.h"
 
+#include "catalog/pg_control.h"
+#include "common/controldata_utils.h"
 #include "libpq-fe.h"
 #include "pqexpbuffer.h"
 
 static char version_file[MAXPGPATH];
 static char pid_file[MAXPGPATH];
 static char backup_file[MAXPGPATH];
-static char recovery_file[MAXPGPATH];
 static char promote_file[MAXPGPATH];
 
 #ifdef WIN32
 static void unlimit_core_size(void);
 #endif
 
+static DBState get_control_dbstate(void);
+
 
 #ifdef WIN32
 static void
                /*
                 * If backup_label exists, an online backup is running. Warn the user
                 * that smart shutdown will wait for it to finish. However, if
-                * recovery.conf is also present, we're recovering from an online
+                * the server is in archive recovery, we're recovering from an online
                 * backup instead of performing one.
                 */
                if (shutdown_mode == SMART_MODE &&
                        stat(backup_file, &statbuf) == 0 &&
-                       stat(recovery_file, &statbuf) != 0)
+                       get_control_dbstate() != DB_IN_ARCHIVE_RECOVERY)
                {
                        print_msg(_("WARNING: online backup mode is active\n"
                                                "Shutdown will not complete until pg_stop_backup() is called.\n\n"));
                /*
                 * If backup_label exists, an online backup is running. Warn the user
                 * that smart shutdown will wait for it to finish. However, if
-                * recovery.conf is also present, we're recovering from an online
+                * the server is in archive recovery, we're recovering from an online
                 * backup instead of performing one.
                 */
                if (shutdown_mode == SMART_MODE &&
                        stat(backup_file, &statbuf) == 0 &&
-                       stat(recovery_file, &statbuf) != 0)
+                       get_control_dbstate() != DB_IN_ARCHIVE_RECOVERY)
                {
                        print_msg(_("WARNING: online backup mode is active\n"
                                                "Shutdown will not complete until pg_stop_backup() is called.\n\n"));
 {
        FILE       *prmfile;
        pgpid_t         pid;
-       struct stat statbuf;
 
        pid = get_pgpid(false);
 
                exit(1);
        }
 
-       /* If recovery.conf doesn't exist, the server is not in standby mode */
-       if (stat(recovery_file, &statbuf) != 0)
+       if (get_control_dbstate() != DB_IN_ARCHIVE_RECOVERY)
        {
                write_stderr(_("%s: cannot promote server; "
                                           "server is not in standby mode\n"),
 }
 
 
+static DBState
+get_control_dbstate(void)
+{
+       DBState ret;
+
+       for (;;)
+       {
+               ControlFileData *control_file_data = get_controlfile(pg_data, progname);
+
+               if (control_file_data)
+               {
+                       ret = control_file_data->state;
+                       pfree(control_file_data);
+                       return ret;
+               }
+
+               if (wait_seconds > 0)
+               {
+                       pg_usleep(1000000);             /* 1 sec */
+                       wait_seconds--;
+                       continue;
+               }
+
+               write_stderr(_("%s: control file appears to be corrupt\n"), progname);
+               exit(1);
+       }
+}
+
+
 int
 main(int argc, char **argv)
 {
                snprintf(version_file, MAXPGPATH, "%s/PG_VERSION", pg_data);
                snprintf(pid_file, MAXPGPATH, "%s/postmaster.pid", pg_data);
                snprintf(backup_file, MAXPGPATH, "%s/backup_label", pg_data);
-               snprintf(recovery_file, MAXPGPATH, "%s/recovery.conf", pg_data);
        }
 
        switch (ctl_command)
 
  *
  * Get controlfile values. The caller is responsible
  * for pfreeing the result.
+ *
+ * Returns NULL if the CRC did not match.
  */
 ControlFileData *
-get_controlfile(char *DataDir, const char *progname)
+get_controlfile(const char *DataDir, const char *progname)
 {
        ControlFileData *ControlFile;
        int                     fd;
        FIN_CRC32C(crc);
 
        if (!EQ_CRC32C(crc, ControlFile->crc))
-#ifndef FRONTEND
-               elog(ERROR, _("calculated CRC checksum does not match value stored in file"));
-#else
-               printf(_("WARNING: Calculated CRC checksum does not match value stored in file.\n"
-                                "Either the file is corrupt, or it has a different layout than this program\n"
-                                "is expecting.  The results below are untrustworthy.\n\n"));
-#endif
+       {
+               pfree(ControlFile);
+               return NULL;
+       }
 
        /* Make sure the control file is valid byte order. */
        if (ControlFile->pg_control_version % 65536 == 0 &&