1111
1212#include <fcntl.h>
1313
14+ #include "common/string.h"
1415#include "pg_upgrade.h"
1516
1617static void check_data_dir (ClusterInfo * cluster );
1718static void check_bin_dir (ClusterInfo * cluster );
1819static void get_bin_version (ClusterInfo * cluster );
19- static void validate_exec (const char * dir , const char * cmdName );
20+ static void check_exec (const char * dir , const char * program );
2021
2122#ifdef WIN32
2223static int win32_check_directory_write_permissions (void );
@@ -375,9 +376,9 @@ check_bin_dir(ClusterInfo *cluster)
375376 report_status (PG_FATAL , "\"%s\" is not a directory\n" ,
376377 cluster -> bindir );
377378
378- validate_exec (cluster -> bindir , "postgres" );
379- validate_exec (cluster -> bindir , "pg_controldata" );
380- validate_exec (cluster -> bindir , "pg_ctl" );
379+ check_exec (cluster -> bindir , "postgres" );
380+ check_exec (cluster -> bindir , "pg_controldata" );
381+ check_exec (cluster -> bindir , "pg_ctl" );
381382
382383 /*
383384 * Fetch the binary version after checking for the existence of pg_ctl.
@@ -388,9 +389,9 @@ check_bin_dir(ClusterInfo *cluster)
388389
389390 /* pg_resetxlog has been renamed to pg_resetwal in version 10 */
390391 if (GET_MAJOR_VERSION (cluster -> bin_version ) <= 906 )
391- validate_exec (cluster -> bindir , "pg_resetxlog" );
392+ check_exec (cluster -> bindir , "pg_resetxlog" );
392393 else
393- validate_exec (cluster -> bindir , "pg_resetwal" );
394+ check_exec (cluster -> bindir , "pg_resetwal" );
394395
395396 if (cluster == & new_cluster )
396397 {
@@ -399,63 +400,46 @@ check_bin_dir(ClusterInfo *cluster)
399400 * pg_dumpall are used to dump the old cluster, but must be of the
400401 * target version.
401402 */
402- validate_exec (cluster -> bindir , "initdb" );
403- validate_exec (cluster -> bindir , "pg_dump" );
404- validate_exec (cluster -> bindir , "pg_dumpall" );
405- validate_exec (cluster -> bindir , "pg_restore" );
406- validate_exec (cluster -> bindir , "psql" );
407- validate_exec (cluster -> bindir , "vacuumdb" );
403+ check_exec (cluster -> bindir , "initdb" );
404+ check_exec (cluster -> bindir , "pg_dump" );
405+ check_exec (cluster -> bindir , "pg_dumpall" );
406+ check_exec (cluster -> bindir , "pg_restore" );
407+ check_exec (cluster -> bindir , "psql" );
408+ check_exec (cluster -> bindir , "vacuumdb" );
408409 }
409410}
410411
411-
412- /*
413- * validate_exec()
414- *
415- * validate "path" as an executable file
416- */
417412static void
418- validate_exec (const char * dir , const char * cmdName )
413+ check_exec (const char * dir , const char * program )
419414{
420- char path [MAXPGPATH ];
421- struct stat buf ;
415+ char path [MAXPGPATH ];
416+ char line [MAXPGPATH ];
417+ char cmd [MAXPGPATH ];
418+ char versionstr [128 ];
419+ int ret ;
422420
423- snprintf (path , sizeof (path ), "%s/%s" , dir , cmdName );
421+ snprintf (path , sizeof (path ), "%s/%s" , dir , program );
424422
425- #ifdef WIN32
426- /* Windows requires a .exe suffix for stat() */
427- if (strlen (path ) <= strlen (EXE_EXT ) ||
428- pg_strcasecmp (path + strlen (path ) - strlen (EXE_EXT ), EXE_EXT ) != 0 )
429- strlcat (path , EXE_EXT , sizeof (path ));
430- #endif
423+ ret = validate_exec (path );
431424
432- /*
433- * Ensure that the file exists and is a regular file.
434- */
435- if (stat (path , & buf ) < 0 )
436- pg_fatal ("check for \"%s\" failed: %s\n" ,
437- path , strerror (errno ));
438- else if (!S_ISREG (buf .st_mode ))
425+ if (ret == -1 )
439426 pg_fatal ("check for \"%s\" failed: not a regular file\n" ,
440427 path );
441-
442- /*
443- * Ensure that the file is both executable and readable (required for
444- * dynamic loading).
445- */
446- #ifndef WIN32
447- if (access (path , R_OK ) != 0 )
448- #else
449- if ((buf .st_mode & S_IRUSR ) == 0 )
450- #endif
451- pg_fatal ("check for \"%s\" failed: cannot read file (permission denied)\n" ,
428+ else if (ret == -2 )
429+ pg_fatal ("check for \"%s\" failed: cannot execute (permission denied)\n" ,
452430 path );
453431
454- #ifndef WIN32
455- if (access (path , X_OK ) != 0 )
456- #else
457- if ((buf .st_mode & S_IXUSR ) == 0 )
458- #endif
459- pg_fatal ("check for \"%s\" failed: cannot execute (permission denied)\n" ,
432+ snprintf (cmd , sizeof (cmd ), "\"%s\" -V" , path );
433+
434+ if (!pipe_read_line (cmd , line , sizeof (line )))
435+ pg_fatal ("check for \"%s\" failed: cannot execute\n" ,
460436 path );
437+
438+ pg_strip_crlf (line );
439+
440+ snprintf (versionstr , sizeof (versionstr ), "%s (PostgreSQL) " PG_VERSION , program );
441+
442+ if (strcmp (line , versionstr ) != 0 )
443+ pg_fatal ("check for \"%s\" failed: incorrect version: found \"%s\", expected \"%s\"\n" ,
444+ path , line , versionstr );
461445}
0 commit comments