The APT problem
When glibc 2.1 was introduced in potato, apt stopped working. Recompiling
fixed it, but I figured this indicated a bug in the compat code, so today
I found time to investigate it. Jason Gunthorpe had provided me with
a test case:
void die(const char *S)
cerr << S << endl;
int main(int argc,const char *argv)
ifstream F(argv,ios::in | ios::nocreate);
if (!F != 0)
streampos Off = F.tellg();
if (!F != 0)
(This has to be run with the name of an existing file as argument.)
When run on a glibc2.1 system, a version compiled with libstdc++2.9
will die with "!F #2". A version compiled with libstdc++2.9-glibc2.1
will exit successfully.
The problem turns out to be rather simple. istream:tellg() contains
streampos pos = _strbuf->pubseekoff(0, ios::cur, ios::in);
streampos pos = _IO_seekoff (_strbuf, 0, _IO_seek_cur, _IOS_INPUT);
if (pos == streampos(EOF))
(This is taken from egcs 1.1.2/libio, a different version than what
generated libstdc++2.9, but I can tell from the disassembly that the
significant part didn't change.)
This code calls _IO_seekoff directly, expecting that it takes a 32-bit
offset. But _IO_seekoff in glibc2.1 takes a 64-bit offset, and ends
up trying to seek to 0x100000000 and failing.
egcs's libio appears to be full of references to glibc's libio.
I checked some others at random (_IO_proc_open, _IO_file_close,
_IO_adjust_column), and found that filebuf::seekoff probably
has the same problem when it calls _IO_file_seekoff, because both
_IO_old_file_seekoff and _IO_new_file_seekoff now take a 64-bit offset.