diff --git a/src/libutil/util.cc b/src/libutil/util.cc index 0b11330..4c1dff2 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -198,17 +198,17 @@ bool pathExists(const Path & path) Path readLink(const Path & path) { checkInterrupt(); - struct stat st = lstat(path); - if (!S_ISLNK(st.st_mode)) - throw Error(format("‘%1%’ is not a symlink") % path); - char buf[st.st_size]; - ssize_t rlsize = readlink(path.c_str(), buf, st.st_size); - if (rlsize == -1) - throw SysError(format("reading symbolic link ‘%1%’") % path); - else if (rlsize > st.st_size) - throw Error(format("symbolic link ‘%1%’ size overflow %2% > %3%") - % path % rlsize % st.st_size); - return string(buf, st.st_size); + for (ssize_t bufSize = PATH_MAX/4; true; bufSize += bufSize/2) { + char buf[bufSize]; + ssize_t rlSize = readlink(path.c_str(), buf, bufSize); + if (rlSize == -1) + if (errno == EINVAL) + throw Error(format("'%1%' is not a symlink") % path); + else + throw SysError(format("reading symbolic link '%1%'") % path); + else if (rlSize < bufSize) + return string(buf, rlSize); + } }