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