> I cannot read the last 4-byte word in a file using lseek + read: > > /* file "foo" exists and is large enough - say, 4 MB */ > int fd = open("foo",O_RDONLY|O_BINARY); > uint32 data; > /* this succeeds and correctly returns the size of file "foo" minus 4 */ > lseek(fd,-sizeof(data),SEEK_END); > /* this returns 0 -- instead of the expected 4 -- and sets errno to ENOENT */ > read(fd,&data,sizeof(data)); > > if I run this under gdb and type > lseek(fd,-sizeof(data),SEEK_END); > read(fd,&data,sizeof(data)); > several times, eventually read() starts to return 4 and set data to the > value I actually wrote into "foo" last. > > I observe this on linux, cygwin and solaris -- what am I doing wrong?
It would have been nicer if you had provided a small example that would compile out of the box; that would show whether you remembered to #include <unistd.h>. One thing you did wrong was not checking the return value of lseek. For all you know, the system might have been trying to tell you your lseek was invalid, but you ignored it and proceeded on with the read anyway. The other thing you did wrong: on cygwin, off_t is a 64-bit signed type, but the sizeof operator is of type size_t, which is only a 32-bit unsigned type. The unary - on an unsigned 32-bit number is an unsigned 32-bit number, then you promote that argument to off_t (32-bit unsigned to 64-bit signed promotion is 0-extended). So you were calling lseek(fd, 0x00000000fffffffcLL, SEEK_END), which is certainly different than the intended lseek(fd, 0xfffffffffffffffcLL, SEEK_END). -- Eric Blake -- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Problem reports: http://cygwin.com/problems.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/