Skip to content

Commit 9200723

Browse files
committed
Improve error reporting from validate_exec().
validate_exec() didn't guarantee to set errno to something appropriate after a failure, leading to callers not being able to print an on-point message. Improve that. Noted by Kyotaro Horiguchi, though this isn't exactly his proposal. Discussion: https://postgr.es/m/20220615.131403.1791191615590453058.horikyota.ntt@gmail.com
1 parent 7652353 commit 9200723

File tree

2 files changed

+16
-11
lines changed

2 files changed

+16
-11
lines changed

src/bin/pg_upgrade/exec.c

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -423,18 +423,11 @@ check_exec(const char *dir, const char *program, bool check_version)
423423
char line[MAXPGPATH];
424424
char cmd[MAXPGPATH];
425425
char versionstr[128];
426-
int ret;
427426

428427
snprintf(path, sizeof(path), "%s/%s", dir, program);
429428

430-
ret = validate_exec(path);
431-
432-
if (ret == -1)
433-
pg_fatal("check for \"%s\" failed: does not exist or cannot be executed",
434-
path);
435-
else if (ret == -2)
436-
pg_fatal("check for \"%s\" failed: cannot read (permission denied)",
437-
path);
429+
if (validate_exec(path) != 0)
430+
pg_fatal("check for \"%s\" failed: %m", path);
438431

439432
snprintf(cmd, sizeof(cmd), "\"%s\" -V", path);
440433

src/common/exec.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ static BOOL GetTokenUser(HANDLE hToken, PTOKEN_USER *ppTokenUser);
7474
* returns 0 if the file is found and no error is encountered.
7575
* -1 if the regular file "path" does not exist or cannot be executed.
7676
* -2 if the file is otherwise valid but cannot be read.
77+
* in the failure cases, errno is set appropriately
7778
*/
7879
int
7980
validate_exec(const char *path)
@@ -105,7 +106,16 @@ validate_exec(const char *path)
105106
return -1;
106107

107108
if (!S_ISREG(buf.st_mode))
109+
{
110+
/*
111+
* POSIX offers no errno code that's simply "not a regular file". If
112+
* it's a directory we can use EISDIR. Otherwise, it's most likely a
113+
* device special file, and EPERM (Operation not permitted) isn't too
114+
* horribly off base.
115+
*/
116+
errno = S_ISDIR(buf.st_mode) ? EISDIR : EPERM;
108117
return -1;
118+
}
109119

110120
/*
111121
* Ensure that the file is both executable and readable (required for
@@ -114,9 +124,11 @@ validate_exec(const char *path)
114124
#ifndef WIN32
115125
is_r = (access(path, R_OK) == 0);
116126
is_x = (access(path, X_OK) == 0);
127+
/* access() will set errno if it returns -1 */
117128
#else
118129
is_r = buf.st_mode & S_IRUSR;
119130
is_x = buf.st_mode & S_IXUSR;
131+
errno = EACCES; /* appropriate thing if we return nonzero */
120132
#endif
121133
return is_x ? (is_r ? 0 : -2) : -1;
122134
}
@@ -165,7 +177,7 @@ find_my_exec(const char *argv0, char *retpath)
165177
return resolve_symlinks(retpath);
166178

167179
log_error(errcode(ERRCODE_WRONG_OBJECT_TYPE),
168-
_("invalid binary \"%s\""), retpath);
180+
_("invalid binary \"%s\": %m"), retpath);
169181
return -1;
170182
}
171183

@@ -215,7 +227,7 @@ find_my_exec(const char *argv0, char *retpath)
215227
break;
216228
case -2: /* found but disqualified */
217229
log_error(errcode(ERRCODE_WRONG_OBJECT_TYPE),
218-
_("could not read binary \"%s\""),
230+
_("could not read binary \"%s\": %m"),
219231
retpath);
220232
break;
221233
}

0 commit comments

Comments
 (0)