* validate_exec -- validate "path" as an executable file * * returns 0 if the file is found and no error is encountered. * -1 if the regular file "path" does not exist or cannot be executed. * -2 if the file is otherwise valid but cannot be read. */
| 68 | * -2 if the file is otherwise valid but cannot be read. |
| 69 | */ |
| 70 | int |
| 71 | validate_exec(const char *path) |
| 72 | { |
| 73 | struct stat buf; |
| 74 | int is_r; |
| 75 | int is_x; |
| 76 | |
| 77 | #ifdef WIN32 |
| 78 | char path_exe[MAXPGPATH + sizeof(".exe") - 1]; |
| 79 | |
| 80 | /* Win32 requires a .exe suffix for stat() */ |
| 81 | if (strlen(path) >= strlen(".exe") && |
| 82 | pg_strcasecmp(path + strlen(path) - strlen(".exe"), ".exe") != 0) |
| 83 | { |
| 84 | strlcpy(path_exe, path, sizeof(path_exe) - 4); |
| 85 | strcat(path_exe, ".exe"); |
| 86 | path = path_exe; |
| 87 | } |
| 88 | #endif |
| 89 | |
| 90 | /* |
| 91 | * Ensure that the file exists and is a regular file. |
| 92 | * |
| 93 | * XXX if you have a broken system where stat() looks at the symlink |
| 94 | * instead of the underlying file, you lose. |
| 95 | */ |
| 96 | if (stat(path, &buf) < 0) |
| 97 | return -1; |
| 98 | |
| 99 | if (!S_ISREG(buf.st_mode)) |
| 100 | return -1; |
| 101 | |
| 102 | /* |
| 103 | * Ensure that the file is both executable and readable (required for |
| 104 | * dynamic loading). |
| 105 | */ |
| 106 | #ifndef WIN32 |
| 107 | is_r = (access(path, R_OK) == 0); |
| 108 | is_x = (access(path, X_OK) == 0); |
| 109 | #else |
| 110 | is_r = buf.st_mode & S_IRUSR; |
| 111 | is_x = buf.st_mode & S_IXUSR; |
| 112 | #endif |
| 113 | return is_x ? (is_r ? 0 : -2) : -1; |
| 114 | } |
| 115 | |
| 116 | |
| 117 | /* |
no test coverage detected