9 Mar 2007 00:05
Bug in pread/pwrite ?
Christophe GRENIER <grenier <at> cgsecurity.org>
2007-03-08 23:05:47 GMT
2007-03-08 23:05:47 GMT
Hi,
After upgrading my compiler from cygwin 1.5.17-1 to 1.5.24-2,
TestDisk & PhotoRec, my GPL data recovery programs, were
unable to read data!
I have written a little program (see attachment) to reproduce
the problem. As administrator, run "test_pread /dev/sda".
The program use lseek() to go the disk end, the function failed.
Now pread will now always failed, because it ends
(cf cygwin-1.5.24-2/newlib/libc/unix/pread.c) by
an lseek to the backuped location. The same problem also applies
to pwrite.
I don't know if the following patch is a good idea:
--- cygwin-1.5.24-2/newlib/libc/unix/pread.org.c 2002-05-06 22:29:28.000000000 +0200
+++ cygwin-1.5.24-2/newlib/libc/unix/pread.c 2007-03-08 23:37:34.000000000 +0100
<at> <at> -70,8 +70,7 <at> <at> _DEFUN (_pread_r, (rptr, fd, buf, n, off
num_read = _read_r (rptr, fd, buf, n);
- if (_lseek_r (rptr, fd, cur_pos, SEEK_SET) == (off_t)-1)
- return -1;
+ _lseek_r (rptr, fd, cur_pos, SEEK_SET);
return (ssize_t)num_read;
}
(Continue reading)
> All of that aside, I don't see how ignoring an lseek() failure
> could be considered to be a good thing.
I have done more research since, have a look to this glibc
pread implementation:
ssize_t
__libc_pread (int fd, void *buf, size_t nbyte, off_t offset)
{
/* Since we must not change the file pointer preserve the value so that
we can restore it later. */
int save_errno;
ssize_t result;
off_t old_offset = __libc_lseek (fd, 0, SEEK_CUR);
if (old_offset == (off_t) -1)
return -1;
/* Set to wanted position. */
if (__libc_lseek (fd, offset, SEEK_SET) == (off_t) -1)
return -1;
/* Write out the data. */
result = __libc_read (fd, buf, nbyte);
RSS Feed