2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-08-30 21:45:37 +00:00

[2572] handled solaris oddity: catch uncommon/buggy results of seekg/tellg.

This commit is contained in:
JINMEI Tatuya
2013-01-14 18:19:03 -08:00
parent 3b38bc023f
commit 84ba4a728f

View File

@@ -36,32 +36,48 @@ createStreamName(const std::istream& input_stream) {
size_t
getStreamSize(std::istream& is) {
errno = 0; // see below
is.seekg(0, std::ios_base::end);
if (is.bad()) {
// This means the istream has an integrity error. It doesn't make
// sense to continue from this point, so we treat it as a fatal error.
isc_throw(InputSource::OpenError,
"failed to seek end of input source");
} else if (is.fail()) {
} else if (is.fail() || errno != 0) {
// This is an error specific to seekg(). There can be several
// reasons, but the most likely cause in this context is that the
// stream is associated with a special type of file such as a pipe.
// In this case, it's more likely that other main operations of
// the input source work fine, so we continue with just setting
// the stream size to "unknown".
//
// (At least some versions of) Solaris + SunStudio shows deviant
// behavior here: It apparently calls lseek(2) internally, but even if
// it fails it doesn't set the error bits of istream. That will
// confuse the rest of this function, so, as a heuristic workaround
// we check errno and handle any non 0 value as fail().
is.clear(); // clear this error not to confuse later ops.
return (MasterLexer::SOURCE_SIZE_UNKNOWN);
}
const std::streampos len = is.tellg();
std::streampos len = is.tellg();
if (len == static_cast<std::streampos>(-1)) { // cast for some compilers
isc_throw(InputSource::OpenError, "failed to get input size");
if (!is.fail()) {
// tellg() returns -1 if istream::fail() would be true, but it's
// not guaranteed that it shouldn't be returned in other cases.
// In fact, with the combination of SunStudio and stlport,
// an stringstream created by the default constructor showed that
// behavior. We treat such cases as an unknown size.
len = MasterLexer::SOURCE_SIZE_UNKNOWN;
} else {
isc_throw(InputSource::OpenError, "failed to get input size");
}
}
is.seekg(0, std::ios::beg);
if (is.fail()) {
isc_throw(InputSource::OpenError,
"failed to seek beginning of input source");
}
assert(len >= 0);
assert(len >= 0 || len == MasterLexer::SOURCE_SIZE_UNKNOWN);
return (len);
}