Bug in pread/pwrite ?
Christophe GRENIER
grenier@cgsecurity.org
Thu Mar 8 23:06:00 GMT 2007
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
@@ -70,8 +70,7 @@ _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;
}
Regards,
Christophe
--
,-~~-.___. ._.
/ | ' \ | |"""""""""| Christophe GRENIER
( ) 0 | | | grenier@cgsecurity.org
\_/-, ,----' | | |
==== !_!--v---v--"
/ \-'~; |""""""""| TestDisk & PhotoRec
/ __/~| ._-""|| | Data Recovery
=( _____|_|____||________| http://www.cgsecurity.org
-------------- next part --------------
#include <sys/types.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main(int argc, char**argv)
{
unsigned char buffer[512];
int fildes;
/* Use a bigger value if your HD is bigger than 1 TB */
off_t too_far=(off_t)1024*1024*1024*1024;
if(argc==1)
{
printf("%s device_to_read\n", argv[1]);
printf("ie: %s /dev/sda\n", argv[1]);
return 1;
}
fildes=open(argv[1], O_RDONLY|O_BINARY);
if(fildes==-1)
{
printf("Can't read %s\n", argv[1]);
}
{
/* Test 1*/
printf("lseek 0 (should be OK): ");
if(lseek(fildes, 0, SEEK_SET)==(off_t)(-1))
{
printf("Failed\n");
return 1;
}
else
printf("OK\n");
/* Test 2*/
printf("pread 0 (should be OK): ");
if(pread(fildes, buffer, 512, 0)==(-1))
{
printf("Failed\n");
return 1;
}
else
printf("OK\n");
/* Test 3: Go at the end of the disk */
printf("lseek after the end of the disk (should be Failed): ");
if(lseek(fildes, too_far, SEEK_SET)==(off_t)(-1))
printf("Failed\n");
else
{
printf("OK\n");
printf("You must use a device, not a file\n");
return 1;
}
/* Test 4*/
printf("pread 0 (should be OK): ");
if(pread(fildes, buffer, 512, 0)==(-1))
printf("Failed <= BUG\n");
else
printf("OK\n");
close(fildes);
}
return 0;
}
More information about the Cygwin-patches
mailing list