fish handling of readlink()

The readlink() function does not null terminate the path it returns.

Remove the OS X code that deals with a path buffer that is too short. For
one thing a loop isn't needed since we're told how big of a buffer
is required if the first _NSGetExecutablePath() call fails. But more
important it is so unlikely that the path will be longer than PATH_MAX
that if it is we should just give up.

Fixes 2931.

(cherry picked from commit 8e103c231e)
This commit is contained in:
Kurtis Rader 2016-04-12 19:03:07 -07:00
parent c2e9cda7b3
commit baee807837

View file

@ -92,39 +92,34 @@ extern "C" {
int _NSGetExecutablePath(char* buf, uint32_t* bufsize); int _NSGetExecutablePath(char* buf, uint32_t* bufsize);
} }
/* Return the path to the current executable. This needs to be realpath'd. */ // Return the path to the current executable. This needs to be realpath'd.
static std::string get_executable_path(const char *argv0) static std::string get_executable_path(const char *argv0)
{ {
char buff[PATH_MAX]; char buff[PATH_MAX + 1];
#if __APPLE__ #if __APPLE__
{ // On OS X use it's proprietary API to get the path to the executable.
/* Returns 0 on success, -1 if the buffer is too small */
uint32_t buffSize = sizeof buff; uint32_t buffSize = sizeof buff;
if (0 == _NSGetExecutablePath(buff, &buffSize)) if (_NSGetExecutablePath(buff, &buffSize) == 0) return std::string(buff);
#else
// On non-OS X UNIXes, try /proc directory.
ssize_t len;
len = readlink("/proc/self/exe", buff, sizeof buff); // Linux
if (len == -1) {
len = readlink("/proc/curproc/file", buff, sizeof buff); // BSD
if (len == -1) {
len = readlink("/proc/self/path/a.out", buff, sizeof buff); // Solaris
}
}
if (len > 0) {
buff[len] = '\0';
return std::string(buff); return std::string(buff);
/* Loop until we're big enough */
char *mbuff = (char *)malloc(buffSize);
while (0 > _NSGetExecutablePath(mbuff, &buffSize))
mbuff = (char *)realloc(mbuff, buffSize);
/* Return the string */
std::string result = mbuff;
free(mbuff);
return result;
} }
#endif #endif
{
/* On other Unixes, try /proc directory. This might be worth breaking out into macros. */
if (0 < readlink("/proc/self/exe", buff, sizeof buff) || // Linux
0 < readlink("/proc/curproc/file", buff, sizeof buff) || // BSD
0 < readlink("/proc/self/path/a.out", buff, sizeof buff)) // Solaris
{
return std::string(buff);
}
}
/* Just return argv0, which probably won't work (i.e. it's not an absolute path or a path relative to the working directory, but instead something the caller found via $PATH). We'll eventually fall back to the compile time paths. */ // Just return argv0, which probably won't work (i.e. it's not an absolute path or a path
// relative to the working directory, but instead something the caller found via $PATH). We'll
// eventually fall back to the compile time paths.
return std::string(argv0 ? argv0 : ""); return std::string(argv0 ? argv0 : "");
} }