* fhandler.h (class fhandler_dev_raw): Delete current_position and
eof_detected status flag. Delete is_eom and is_eof methods. Move drive_size, bytes_per_sector, eom_detected status flag, as well as the methods read_file, write_file, raw_read and raw_write to ... (class fhandler_dev_floppy): ... here. Remove is_eom and is_eof methods. Add dup method. * fhandler_floppy.cc (IS_EOM): New macro. (fhandler_dev_floppy::is_eom): Remove. (fhandler_dev_floppy::is_eof): Remove. (fhandler_dev_floppy::fhandler_dev_floppy): Initialize status flags. (fhandler_dev_floppy::get_drive_info): Only call EX functions on systems supporting them and stop suffering strange delays. (fhandler_dev_floppy::read_file): Move here, drop setting current_position. (fhandler_dev_floppy::write_file): Move here, drop setting current_position. (fhandler_dev_floppy::open): Rearrange comment. (fhandler_dev_floppy::dup): New method. (fhandler_dev_floppy::get_current_position): New inline method. Use instead of former current_position were appropriate. (fhandler_dev_floppy::raw_read): Move here. Drop EOF handling. (fhandler_dev_floppy::raw_write): Move here. Drop EOF handling. (fhandler_dev_floppy::lseek): Remove useless conditions. Convert sector_aligned_offset to LARGE_INTEGER to improve SetFilePointer call. (fhandler_dev_floppy::ioctl): Move blocksize check in RDSETBLK case to here. * fhandler_raw.cc (fhandler_dev_raw::is_eom): Remove. (fhandler_dev_raw::is_eof): Remove. (fhandler_dev_raw::write_file): Remove. (fhandler_dev_raw::read_file): Remove. (fhandler_dev_raw::raw_read): Remove. (fhandler_dev_raw::raw_write): Remove. (fhandler_dev_raw::dup): Drop copying removed members. (fhandler_dev_raw::ioctl): Drop blocksize testing. * wincap.h: Implement has_disk_ex_ioctls throughout. * wincap.cc: Ditto. (wincap_vista): Preliminary wincaps for Windows Vista/Longhorn. (wincapc::init): Add Vista/Longhorn handling.
This commit is contained in:
		| @@ -1,3 +1,44 @@ | ||||
| 2005-09-28  Corinna Vinschen  <corinna@vinschen.de> | ||||
|  | ||||
| 	* fhandler.h (class fhandler_dev_raw): Delete current_position and | ||||
| 	eof_detected status flag.  Delete is_eom and is_eof methods. | ||||
| 	Move drive_size, bytes_per_sector, eom_detected status flag, as well | ||||
| 	as the methods read_file, write_file, raw_read and raw_write to ... | ||||
| 	(class fhandler_dev_floppy): ... here. Remove is_eom and is_eof | ||||
| 	methods.  Add dup method. | ||||
| 	* fhandler_floppy.cc (IS_EOM): New macro. | ||||
| 	(fhandler_dev_floppy::is_eom): Remove. | ||||
| 	(fhandler_dev_floppy::is_eof): Remove. | ||||
| 	(fhandler_dev_floppy::fhandler_dev_floppy): Initialize status flags. | ||||
| 	(fhandler_dev_floppy::get_drive_info): Only call EX functions on | ||||
| 	systems supporting them and stop suffering strange delays. | ||||
| 	(fhandler_dev_floppy::read_file): Move here, drop setting | ||||
| 	current_position. | ||||
| 	(fhandler_dev_floppy::write_file): Move here, drop setting | ||||
| 	current_position. | ||||
| 	(fhandler_dev_floppy::open): Rearrange comment. | ||||
| 	(fhandler_dev_floppy::dup): New method. | ||||
| 	(fhandler_dev_floppy::get_current_position): New inline method.  Use | ||||
| 	instead of former current_position were appropriate. | ||||
| 	(fhandler_dev_floppy::raw_read): Move here.  Drop EOF handling. | ||||
| 	(fhandler_dev_floppy::raw_write): Move here.  Drop EOF handling. | ||||
| 	(fhandler_dev_floppy::lseek): Remove useless conditions.  Convert | ||||
| 	sector_aligned_offset to LARGE_INTEGER to improve SetFilePointer call. | ||||
| 	(fhandler_dev_floppy::ioctl): Move blocksize check in RDSETBLK case | ||||
| 	to here. | ||||
| 	* fhandler_raw.cc (fhandler_dev_raw::is_eom): Remove. | ||||
| 	(fhandler_dev_raw::is_eof): Remove. | ||||
| 	(fhandler_dev_raw::write_file): Remove. | ||||
| 	(fhandler_dev_raw::read_file): Remove. | ||||
| 	(fhandler_dev_raw::raw_read): Remove. | ||||
| 	(fhandler_dev_raw::raw_write): Remove. | ||||
| 	(fhandler_dev_raw::dup): Drop copying removed members. | ||||
| 	(fhandler_dev_raw::ioctl): Drop blocksize testing. | ||||
| 	* wincap.h: Implement has_disk_ex_ioctls throughout. | ||||
| 	* wincap.cc: Ditto. | ||||
| 	(wincap_vista): Preliminary wincaps for Windows Vista/Longhorn. | ||||
| 	(wincapc::init): Add Vista/Longhorn handling. | ||||
|  | ||||
| 2005-09-28  Christopher Faylor  <cgf@timesys.com> | ||||
|  | ||||
| 	* dcrt0.cc (getstack): New function. | ||||
|   | ||||
| @@ -551,50 +551,29 @@ public: | ||||
| class fhandler_dev_raw: public fhandler_base | ||||
| { | ||||
|  protected: | ||||
|   _off64_t drive_size; | ||||
|   _off64_t current_position; | ||||
|   unsigned long bytes_per_sector; | ||||
|   char *devbuf; | ||||
|   size_t devbufsiz; | ||||
|   size_t devbufstart; | ||||
|   size_t devbufend; | ||||
|   struct status_flags | ||||
|   { | ||||
|     unsigned eom_detected    : 1; | ||||
|     unsigned eof_detected    : 1; | ||||
|     unsigned lastblk_to_read : 1; | ||||
|    public: | ||||
|     status_flags () : | ||||
|       eom_detected (0), eof_detected (0), lastblk_to_read (0) | ||||
|       {} | ||||
|     status_flags () : lastblk_to_read (0) {} | ||||
|   } status; | ||||
|  | ||||
|   IMPLEMENT_STATUS_FLAG (bool, eom_detected) | ||||
|   IMPLEMENT_STATUS_FLAG (bool, eof_detected) | ||||
|   IMPLEMENT_STATUS_FLAG (bool, lastblk_to_read) | ||||
|  | ||||
|   virtual BOOL write_file (const void *buf, DWORD to_write, | ||||
| 			   DWORD *written, int *err); | ||||
|   virtual BOOL read_file (void *buf, DWORD to_read, DWORD *read, int *err); | ||||
|  | ||||
|   /* returns not null, if `win_error' determines an end of media condition */ | ||||
|   virtual int is_eom(int win_error); | ||||
|   /* returns not null, if `win_error' determines an end of file condition */ | ||||
|   virtual int is_eof(int win_error); | ||||
|  | ||||
|   fhandler_dev_raw (); | ||||
|  | ||||
|  public: | ||||
|   ~fhandler_dev_raw (); | ||||
|  | ||||
|   int open (int flags, mode_t mode = 0); | ||||
|   void raw_read (void *ptr, size_t& ulen); | ||||
|   int raw_write (const void *ptr, size_t ulen); | ||||
|  | ||||
|   int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2))); | ||||
|  | ||||
|   int dup (fhandler_base *child); | ||||
|  | ||||
|   int ioctl (unsigned int cmd, void *buf); | ||||
|  | ||||
|   void fixup_after_fork (HANDLE); | ||||
| @@ -604,20 +583,32 @@ class fhandler_dev_raw: public fhandler_base | ||||
| class fhandler_dev_floppy: public fhandler_dev_raw | ||||
| { | ||||
|  private: | ||||
|   _off64_t drive_size; | ||||
|   unsigned long bytes_per_sector; | ||||
|   struct status_flags | ||||
|   { | ||||
|     unsigned eom_detected    : 1; | ||||
|    public: | ||||
|     status_flags () : eom_detected (0) {} | ||||
|   } status; | ||||
|  | ||||
|   IMPLEMENT_STATUS_FLAG (bool, eom_detected) | ||||
|  | ||||
|   inline _off64_t get_current_position (); | ||||
|   int fhandler_dev_floppy::get_drive_info (struct hd_geometry *geo); | ||||
|  | ||||
|  protected: | ||||
|   virtual int is_eom (int win_error); | ||||
|   virtual int is_eof (int win_error); | ||||
|   BOOL write_file (const void *buf, DWORD to_write, DWORD *written, int *err); | ||||
|   BOOL read_file (void *buf, DWORD to_read, DWORD *read, int *err); | ||||
|  | ||||
|  public: | ||||
|   fhandler_dev_floppy (); | ||||
|  | ||||
|   virtual int open (int flags, mode_t mode = 0); | ||||
|  | ||||
|   virtual _off64_t lseek (_off64_t offset, int whence); | ||||
|  | ||||
|   virtual int ioctl (unsigned int cmd, void *buf); | ||||
|   int open (int flags, mode_t mode = 0); | ||||
|   int dup (fhandler_base *child); | ||||
|   void raw_read (void *ptr, size_t& ulen); | ||||
|   int raw_write (const void *ptr, size_t ulen); | ||||
|   _off64_t lseek (_off64_t offset, int whence); | ||||
|   int ioctl (unsigned int cmd, void *buf); | ||||
| }; | ||||
|  | ||||
| class fhandler_dev_tape: public fhandler_dev_raw | ||||
|   | ||||
| @@ -14,6 +14,7 @@ details. */ | ||||
| #include <unistd.h> | ||||
| #include <winioctl.h> | ||||
| #include <asm/socket.h> | ||||
| #include <cygwin/rdevio.h> | ||||
| #include <cygwin/hdreg.h> | ||||
| #include <cygwin/fs.h> | ||||
| #include "cygerrno.h" | ||||
| @@ -21,31 +22,15 @@ details. */ | ||||
| #include "path.h" | ||||
| #include "fhandler.h" | ||||
|  | ||||
| #define IS_EOM(err)	((err) == ERROR_INVALID_PARAMETER \ | ||||
| 			 || (err) == ERROR_SEEK \ | ||||
| 			 || (err) == ERROR_SECTOR_NOT_FOUND) | ||||
|  | ||||
| /**********************************************************************/ | ||||
| /* fhandler_dev_floppy */ | ||||
|  | ||||
| int | ||||
| fhandler_dev_floppy::is_eom (int win_error) | ||||
| { | ||||
|   int ret = (win_error == ERROR_INVALID_PARAMETER | ||||
| 	     || win_error == ERROR_SEEK | ||||
| 	     || win_error == ERROR_SECTOR_NOT_FOUND); | ||||
|   if (ret) | ||||
|     debug_printf ("end of medium"); | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| int | ||||
| fhandler_dev_floppy::is_eof (int) | ||||
| { | ||||
|   int ret = 0; | ||||
|   if (ret) | ||||
|     debug_printf ("end of file"); | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| fhandler_dev_floppy::fhandler_dev_floppy () | ||||
|   : fhandler_dev_raw () | ||||
|   : fhandler_dev_raw (), status () | ||||
| { | ||||
| } | ||||
|  | ||||
| @@ -62,9 +47,22 @@ fhandler_dev_floppy::get_drive_info (struct hd_geometry *geo) | ||||
|  | ||||
|   /* Always try using the new EX ioctls first (>= XP).  If not available, | ||||
|      fall back to trying the old non-EX ioctls. */ | ||||
|   if (!DeviceIoControl (get_handle (), | ||||
| 			IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0, | ||||
| 			dbuf, 256, &bytes_read, NULL)) | ||||
|   if (wincap.has_disk_ex_ioctls ()) | ||||
|     { | ||||
|       if (!DeviceIoControl (get_handle (), | ||||
| 			    IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0, | ||||
| 			    dbuf, 256, &bytes_read, NULL)) | ||||
| 	{ | ||||
| 	  __seterrno (); | ||||
| 	  return -1; | ||||
| 	} | ||||
|       di = &((DISK_GEOMETRY_EX *) dbuf)->Geometry; | ||||
|       if (DeviceIoControl (get_handle (), | ||||
| 			   IOCTL_DISK_GET_PARTITION_INFO_EX, NULL, 0, | ||||
| 			   pbuf, 256, &bytes_read, NULL)) | ||||
| 	pix = (PARTITION_INFORMATION_EX *) pbuf; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       if (!DeviceIoControl (get_handle (), | ||||
| 			    IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, | ||||
| @@ -74,18 +72,11 @@ fhandler_dev_floppy::get_drive_info (struct hd_geometry *geo) | ||||
| 	  return -1; | ||||
| 	} | ||||
|       di = (DISK_GEOMETRY *) dbuf; | ||||
|       if (DeviceIoControl (get_handle (), | ||||
| 			   IOCTL_DISK_GET_PARTITION_INFO, NULL, 0, | ||||
| 			   pbuf, 256, &bytes_read, NULL)) | ||||
| 	pi = (PARTITION_INFORMATION *) pbuf; | ||||
|     } | ||||
|   else | ||||
|     di = &((DISK_GEOMETRY_EX *) dbuf)->Geometry; | ||||
|      | ||||
|   if (DeviceIoControl (get_handle (), | ||||
| 		       IOCTL_DISK_GET_PARTITION_INFO_EX, NULL, 0, | ||||
| 		       pbuf, 256, &bytes_read, NULL)) | ||||
|     pix = (PARTITION_INFORMATION_EX *) pbuf; | ||||
|   else if (DeviceIoControl (get_handle (), | ||||
| 			    IOCTL_DISK_GET_PARTITION_INFO, NULL, 0, | ||||
| 			    pbuf, 256, &bytes_read, NULL)) | ||||
|     pi = (PARTITION_INFORMATION *) pbuf; | ||||
|  | ||||
|   debug_printf ("disk geometry: (%ld cyl)*(%ld trk)*(%ld sec)*(%ld bps)", | ||||
| 		 di->Cylinders.LowPart, | ||||
| @@ -132,22 +123,46 @@ fhandler_dev_floppy::get_drive_info (struct hd_geometry *geo) | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| /* Wrapper functions for ReadFile and WriteFile to simplify error handling. */ | ||||
| BOOL | ||||
| fhandler_dev_floppy::read_file (void *buf, DWORD to_read, DWORD *read, int *err) | ||||
| { | ||||
|   BOOL ret; | ||||
|  | ||||
|   *err = 0; | ||||
|   if (!(ret = ReadFile (get_handle (), buf, to_read, read, 0))) | ||||
|     *err = GetLastError (); | ||||
|   syscall_printf ("%d (err %d) = ReadFile (%d, %d, to_read %d, read %d, 0)", | ||||
| 		  ret, *err, get_handle (), buf, to_read, *read); | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| BOOL | ||||
| fhandler_dev_floppy::write_file (const void *buf, DWORD to_write, | ||||
| 				 DWORD *written, int *err) | ||||
| { | ||||
|   BOOL ret; | ||||
|  | ||||
|   *err = 0; | ||||
|   if (!(ret = WriteFile (get_handle (), buf, to_write, written, 0))) | ||||
|     *err = GetLastError (); | ||||
|   syscall_printf ("%d (err %d) = WriteFile (%d, %d, write %d, written %d, 0)", | ||||
| 		  ret, *err, get_handle (), buf, to_write, *written); | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| int | ||||
| fhandler_dev_floppy::open (int flags, mode_t) | ||||
| { | ||||
|   /* The correct size of the buffer would be 512 bytes, | ||||
|    * which is the atomic size, supported by WinNT. | ||||
|    * Unfortunately, the performance is worse than | ||||
|    * access to file system on same device! | ||||
|    * Setting buffer size to a relatively big value | ||||
|    * increases performance by means. | ||||
|    * The new ioctl call with 'rdevio.h' header file | ||||
|    * supports changing this value. | ||||
|    * | ||||
|    * Let's be smart: Let's take a multiplier of typical tar | ||||
|    * and cpio buffer sizes by default! | ||||
|   */ | ||||
|   devbufsiz = 61440L; /* 512L; */ | ||||
|   /* The correct size of the buffer would be 512 bytes, which is the atomic | ||||
|      size, supported by WinNT.  Unfortunately, the performance is worse than | ||||
|      access to file system on same device!  Setting buffer size to a | ||||
|      relatively big value increases performance by means.  The new ioctl call | ||||
|      with 'rdevio.h' header file supports changing this value. | ||||
|  | ||||
|      Let's try to be smart: Let's take a multiple of typical tar and cpio | ||||
|      buffer sizes by default. */ | ||||
|   devbufsiz = 61440L; | ||||
|   int ret =  fhandler_dev_raw::open (flags); | ||||
|  | ||||
|   if (ret && get_drive_info (NULL)) | ||||
| @@ -159,59 +174,244 @@ fhandler_dev_floppy::open (int flags, mode_t) | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| int | ||||
| fhandler_dev_floppy::dup (fhandler_base *child) | ||||
| { | ||||
|   int ret = fhandler_dev_raw::dup (child); | ||||
|  | ||||
|   if (!ret) | ||||
|     { | ||||
|       fhandler_dev_floppy *fhc = (fhandler_dev_floppy *) child; | ||||
|  | ||||
|       fhc->drive_size = drive_size; | ||||
|       fhc->bytes_per_sector = bytes_per_sector; | ||||
|       fhc->eom_detected (eom_detected ()); | ||||
|     } | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| inline _off64_t | ||||
| fhandler_dev_floppy::get_current_position () | ||||
| { | ||||
|   LARGE_INTEGER off = { QuadPart: 0LL }; | ||||
|   off.LowPart = SetFilePointer (get_handle (), 0, &off.HighPart, FILE_CURRENT); | ||||
|   return off.QuadPart; | ||||
| } | ||||
|  | ||||
| void | ||||
| fhandler_dev_floppy::raw_read (void *ptr, size_t& ulen) | ||||
| { | ||||
|   DWORD bytes_read = 0; | ||||
|   DWORD read2; | ||||
|   DWORD bytes_to_read; | ||||
|   int ret; | ||||
|   size_t len = ulen; | ||||
|   char *tgt; | ||||
|   char *p = (char *) ptr; | ||||
|  | ||||
|   /* Checking a previous end of media */ | ||||
|   if (eom_detected () && !lastblk_to_read ()) | ||||
|     { | ||||
|       set_errno (ENOSPC); | ||||
|       goto err; | ||||
|     } | ||||
|  | ||||
|   if (devbuf) | ||||
|     { | ||||
|       while (len > 0) | ||||
| 	{ | ||||
| 	  if (devbufstart < devbufend) | ||||
| 	    { | ||||
| 	      bytes_to_read = min (len, devbufend - devbufstart); | ||||
| 	      debug_printf ("read %d bytes from buffer (rest %d)", | ||||
| 			    bytes_to_read, | ||||
| 			    devbufend - devbufstart - bytes_to_read); | ||||
| 	      memcpy (p, devbuf + devbufstart, bytes_to_read); | ||||
| 	      len -= bytes_to_read; | ||||
| 	      p += bytes_to_read; | ||||
| 	      bytes_read += bytes_to_read; | ||||
| 	      devbufstart += bytes_to_read; | ||||
|  | ||||
| 	      if (lastblk_to_read ()) | ||||
| 		{ | ||||
| 		  lastblk_to_read (false); | ||||
| 		  break; | ||||
| 		} | ||||
| 	    } | ||||
| 	  if (len > 0) | ||||
| 	    { | ||||
| 	      if (len >= devbufsiz) | ||||
| 		{ | ||||
| 		  bytes_to_read = (len / bytes_per_sector) * bytes_per_sector; | ||||
| 		  tgt = p; | ||||
| 		} | ||||
| 	      else | ||||
| 		{ | ||||
| 		  tgt = devbuf; | ||||
| 		  bytes_to_read = devbufsiz; | ||||
| 		} | ||||
| 	      _off64_t current_position = get_current_position (); | ||||
| 	      if (current_position + bytes_to_read >= drive_size) | ||||
| 		bytes_to_read = drive_size - current_position; | ||||
| 	      if (!bytes_to_read) | ||||
| 		{ | ||||
| 		  eom_detected (true); | ||||
| 		  break; | ||||
| 		} | ||||
|  | ||||
| 	      debug_printf ("read %d bytes %s", bytes_to_read, | ||||
| 			    len < devbufsiz ? "into buffer" : "directly"); | ||||
| 	      if (!read_file (tgt, bytes_to_read, &read2, &ret)) | ||||
| 		{ | ||||
| 		  if (!IS_EOM (ret)) | ||||
| 		    { | ||||
| 		      __seterrno (); | ||||
| 		      goto err; | ||||
| 		    } | ||||
|  | ||||
| 		  eom_detected (true); | ||||
|  | ||||
| 		  if (!read2) | ||||
| 		    { | ||||
| 		      if (!bytes_read) | ||||
| 			{ | ||||
| 			  debug_printf ("return -1, set errno to ENOSPC"); | ||||
| 			  set_errno (ENOSPC); | ||||
| 			  goto err; | ||||
| 			} | ||||
| 		      break; | ||||
| 		    } | ||||
| 		  lastblk_to_read (true); | ||||
| 		} | ||||
| 	      if (!read2) | ||||
| 	       break; | ||||
| 	      if (tgt == devbuf) | ||||
| 		{ | ||||
| 		  devbufstart = 0; | ||||
| 		  devbufend = read2; | ||||
| 		} | ||||
| 	      else | ||||
| 		{ | ||||
| 		  len -= read2; | ||||
| 		  p += read2; | ||||
| 		  bytes_read += read2; | ||||
| 		} | ||||
| 	    } | ||||
| 	} | ||||
|     } | ||||
|   else if (!read_file (p, len, &bytes_read, &ret)) | ||||
|     { | ||||
|       if (!IS_EOM (ret)) | ||||
| 	{ | ||||
| 	  __seterrno (); | ||||
| 	  goto err; | ||||
| 	} | ||||
|       if (bytes_read) | ||||
| 	eom_detected (true); | ||||
|       else | ||||
| 	{ | ||||
| 	  debug_printf ("return -1, set errno to ENOSPC"); | ||||
| 	  set_errno (ENOSPC); | ||||
| 	  goto err; | ||||
| 	} | ||||
|     } | ||||
|  | ||||
|   ulen = (size_t) bytes_read; | ||||
|   return; | ||||
|  | ||||
| err: | ||||
|   ulen = (size_t) -1; | ||||
| } | ||||
|  | ||||
| int | ||||
| fhandler_dev_floppy::raw_write (const void *ptr, size_t len) | ||||
| { | ||||
|   DWORD bytes_written = 0; | ||||
|   char *p = (char *) ptr; | ||||
|   int ret; | ||||
|  | ||||
|   /* Checking a previous end of media on tape */ | ||||
|   if (eom_detected ()) | ||||
|     { | ||||
|       set_errno (ENOSPC); | ||||
|       return -1; | ||||
|     } | ||||
|  | ||||
|   /* Invalidate buffer. */ | ||||
|   devbufstart = devbufend = 0; | ||||
|  | ||||
|   if (len > 0) | ||||
|     { | ||||
|       if (!write_file (p, len, &bytes_written, &ret)) | ||||
| 	{ | ||||
| 	  if (!IS_EOM (ret)) | ||||
| 	    { | ||||
| 	      __seterrno (); | ||||
| 	      return -1; | ||||
| 	    } | ||||
| 	  eom_detected (true); | ||||
| 	  if (!bytes_written) | ||||
| 	    { | ||||
| 	      set_errno (ENOSPC); | ||||
| 	      return -1; | ||||
| 	    } | ||||
| 	} | ||||
|     } | ||||
|   return bytes_written; | ||||
| } | ||||
|  | ||||
| _off64_t | ||||
| fhandler_dev_floppy::lseek (_off64_t offset, int whence) | ||||
| { | ||||
|   char buf[512]; | ||||
|   _off64_t lloffset = offset; | ||||
|   _off64_t sector_aligned_offset; | ||||
|   LARGE_INTEGER sector_aligned_offset; | ||||
|   _off64_t bytes_left; | ||||
|   DWORD low; | ||||
|   LONG high = 0; | ||||
|  | ||||
|   if (whence == SEEK_END && drive_size > 0) | ||||
|   if (whence == SEEK_END) | ||||
|     { | ||||
|       lloffset = offset + drive_size; | ||||
|       lloffset += drive_size; | ||||
|       whence = SEEK_SET; | ||||
|     } | ||||
|   else if (whence == SEEK_CUR) | ||||
|     { | ||||
|       lloffset += get_current_position () - (devbufend - devbufstart); | ||||
|       whence = SEEK_SET; | ||||
|     } | ||||
|  | ||||
|   if (whence == SEEK_CUR) | ||||
|     { | ||||
|       lloffset += current_position - (devbufend - devbufstart); | ||||
|       whence = SEEK_SET; | ||||
|     } | ||||
|  | ||||
|   if (whence != SEEK_SET | ||||
|       || lloffset < 0 | ||||
|       || drive_size > 0 && lloffset >= drive_size) | ||||
|   if (whence != SEEK_SET || lloffset < 0 || lloffset >= drive_size) | ||||
|     { | ||||
|       set_errno (EINVAL); | ||||
|       return -1; | ||||
|     } | ||||
|  | ||||
|   sector_aligned_offset = (lloffset / bytes_per_sector) * bytes_per_sector; | ||||
|   bytes_left = lloffset - sector_aligned_offset; | ||||
|   sector_aligned_offset.QuadPart = (lloffset / bytes_per_sector) | ||||
| 				   * bytes_per_sector; | ||||
|   bytes_left = lloffset - sector_aligned_offset.QuadPart; | ||||
|  | ||||
|   /* Invalidate buffer. */ | ||||
|   devbufstart = devbufend = 0; | ||||
|  | ||||
|   low = sector_aligned_offset & UINT32_MAX; | ||||
|   high = sector_aligned_offset >> 32; | ||||
|   if (SetFilePointer (get_handle (), low, &high, FILE_BEGIN) | ||||
|       == INVALID_SET_FILE_POINTER && GetLastError ()) | ||||
|   sector_aligned_offset.LowPart = | ||||
| 			SetFilePointer (get_handle (), | ||||
| 					sector_aligned_offset.LowPart, | ||||
| 					§or_aligned_offset.HighPart, | ||||
| 					FILE_BEGIN); | ||||
|   if (sector_aligned_offset.LowPart == INVALID_SET_FILE_POINTER | ||||
|       && GetLastError ()) | ||||
|     { | ||||
|       __seterrno (); | ||||
|       return -1; | ||||
|     } | ||||
|  | ||||
|   eom_detected (false); | ||||
|   current_position = sector_aligned_offset; | ||||
|  | ||||
|   if (bytes_left) | ||||
|     { | ||||
|       size_t len = bytes_left; | ||||
|       raw_read (buf, len); | ||||
|     } | ||||
|   return current_position + bytes_left; | ||||
|   return sector_aligned_offset.QuadPart + bytes_left; | ||||
| } | ||||
|  | ||||
| int | ||||
| @@ -257,6 +457,18 @@ fhandler_dev_floppy::ioctl (unsigned int cmd, void *buf) | ||||
| 	*(int *)buf = bytes_per_sector; | ||||
| 	return 0; | ||||
|       } | ||||
|     case RDSETBLK: | ||||
|       /* Just check the restriction that blocksize must be a multiple | ||||
|          of the sector size of the underlying volume sector size, | ||||
| 	 then fall through to fhandler_dev_raw::ioctl. */ | ||||
|       struct rdop *op = (struct rdop *) buf; | ||||
|       if (op->rd_parm % bytes_per_sector) | ||||
| 	{ | ||||
| 	  SetLastError (ERROR_INVALID_PARAMETER); | ||||
| 	  __seterrno (); | ||||
| 	  return -1; | ||||
| 	} | ||||
|       /*FALLTHRUGH*/ | ||||
|     default: | ||||
|       return fhandler_dev_raw::ioctl (cmd, buf); | ||||
|     } | ||||
|   | ||||
| @@ -27,52 +27,6 @@ | ||||
| /**********************************************************************/ | ||||
| /* fhandler_dev_raw */ | ||||
|  | ||||
| int | ||||
| fhandler_dev_raw::is_eom (int win_error) | ||||
| { | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| int | ||||
| fhandler_dev_raw::is_eof (int) | ||||
| { | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* Wrapper functions to simplify error handling. */ | ||||
|  | ||||
| BOOL | ||||
| fhandler_dev_raw::write_file (const void *buf, DWORD to_write, | ||||
| 			      DWORD *written, int *err) | ||||
| { | ||||
|   BOOL ret; | ||||
|  | ||||
|   *err = 0; | ||||
|   if (!(ret = WriteFile (get_handle (), buf, to_write, written, 0))) | ||||
|     *err = GetLastError (); | ||||
|   else | ||||
|     current_position += *written; | ||||
|   syscall_printf ("%d (err %d) = WriteFile (%d, %d, write %d, written %d, 0)", | ||||
| 		  ret, *err, get_handle (), buf, to_write, *written); | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| BOOL | ||||
| fhandler_dev_raw::read_file (void *buf, DWORD to_read, DWORD *read, int *err) | ||||
| { | ||||
|   BOOL ret; | ||||
|  | ||||
|   *err = 0; | ||||
|   if (!(ret = ReadFile (get_handle (), buf, to_read, read, 0))) | ||||
|     *err = GetLastError (); | ||||
|   else | ||||
|     current_position += *read; | ||||
|   syscall_printf ("%d (err %d) = ReadFile (%d, %d, to_read %d, read %d, 0)", | ||||
| 		  ret, *err, get_handle (), buf, to_read, *read); | ||||
|   return ret; | ||||
| } | ||||
|  | ||||
| fhandler_dev_raw::fhandler_dev_raw () | ||||
|   : fhandler_base (), status () | ||||
| { | ||||
| @@ -140,205 +94,20 @@ fhandler_dev_raw::open (int flags, mode_t) | ||||
|   return res; | ||||
| } | ||||
|  | ||||
| void | ||||
| fhandler_dev_raw::raw_read (void *ptr, size_t& ulen) | ||||
| { | ||||
|   DWORD bytes_read = 0; | ||||
|   DWORD read2; | ||||
|   DWORD bytes_to_read; | ||||
|   int ret; | ||||
|   size_t len = ulen; | ||||
|   char *tgt; | ||||
|   char *p = (char *) ptr; | ||||
|  | ||||
|   /* Checking a previous end of file */ | ||||
|   if (eof_detected () && !lastblk_to_read ()) | ||||
|     { | ||||
|       eof_detected (false); | ||||
|       ulen = 0; | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   /* Checking a previous end of media */ | ||||
|   if (eom_detected () && !lastblk_to_read ()) | ||||
|     { | ||||
|       set_errno (ENOSPC); | ||||
|       goto err; | ||||
|     } | ||||
|  | ||||
|   if (devbuf) | ||||
|     { | ||||
|       while (len > 0) | ||||
| 	{ | ||||
| 	  if (devbufstart < devbufend) | ||||
| 	    { | ||||
| 	      bytes_to_read = min (len, devbufend - devbufstart); | ||||
| 	      debug_printf ("read %d bytes from buffer (rest %d)", | ||||
| 			    bytes_to_read, | ||||
| 			    devbufend - devbufstart - bytes_to_read); | ||||
| 	      memcpy (p, devbuf + devbufstart, bytes_to_read); | ||||
| 	      len -= bytes_to_read; | ||||
| 	      p += bytes_to_read; | ||||
| 	      bytes_read += bytes_to_read; | ||||
| 	      devbufstart += bytes_to_read; | ||||
|  | ||||
| 	      if (lastblk_to_read ()) | ||||
| 		{ | ||||
| 		  lastblk_to_read (false); | ||||
| 		  break; | ||||
| 		} | ||||
| 	    } | ||||
| 	  if (len > 0) | ||||
| 	    { | ||||
| 	      if (len >= devbufsiz) | ||||
| 		{ | ||||
| 		  bytes_to_read = (len / bytes_per_sector) * bytes_per_sector; | ||||
| 		  if (current_position + bytes_to_read >= drive_size) | ||||
| 		    bytes_to_read = drive_size - current_position; | ||||
| 		  tgt = p; | ||||
| 		  debug_printf ("read %d bytes direct from file",bytes_to_read); | ||||
| 		} | ||||
| 	      else | ||||
| 		{ | ||||
| 		  tgt = devbuf; | ||||
| 		  bytes_to_read = devbufsiz; | ||||
| 		  if (current_position + bytes_to_read >= drive_size) | ||||
| 		    bytes_to_read = drive_size - current_position; | ||||
| 		  debug_printf ("read %d bytes from file into buffer", | ||||
| 				bytes_to_read); | ||||
| 		} | ||||
| 	      if (!bytes_to_read) | ||||
| 		{ | ||||
| 		  eom_detected (true); | ||||
| 		  break; | ||||
| 		} | ||||
|  | ||||
| 	      if (!read_file (tgt, bytes_to_read, &read2, &ret)) | ||||
| 		{ | ||||
| 		  if (!is_eof (ret) && !is_eom (ret)) | ||||
| 		    { | ||||
| 		      __seterrno (); | ||||
| 		      goto err; | ||||
| 		    } | ||||
|  | ||||
| 		  if (is_eof (ret)) | ||||
| 		    eof_detected (true); | ||||
| 		  else | ||||
| 		    eom_detected (true); | ||||
|  | ||||
| 		  if (!read2) | ||||
| 		    { | ||||
| 		      if (!bytes_read && is_eom (ret)) | ||||
| 			{ | ||||
| 			  debug_printf ("return -1, set errno to ENOSPC"); | ||||
| 			  set_errno (ENOSPC); | ||||
| 			  goto err; | ||||
| 			} | ||||
| 		      break; | ||||
| 		    } | ||||
| 		  lastblk_to_read (true); | ||||
| 		} | ||||
| 	      if (!read2) | ||||
| 	       break; | ||||
| 	      if (tgt == devbuf) | ||||
| 		{ | ||||
| 		  devbufstart = 0; | ||||
| 		  devbufend = read2; | ||||
| 		} | ||||
| 	      else | ||||
| 		{ | ||||
| 		  len -= read2; | ||||
| 		  p += read2; | ||||
| 		  bytes_read += read2; | ||||
| 		} | ||||
| 	    } | ||||
| 	} | ||||
|     } | ||||
|   else if (!read_file (p, len, &bytes_read, &ret)) | ||||
|     { | ||||
|       if (!is_eof (ret) && !is_eom (ret)) | ||||
| 	{ | ||||
| 	  __seterrno (); | ||||
| 	  goto err; | ||||
| 	} | ||||
|       if (bytes_read) | ||||
| 	{ | ||||
| 	  if (is_eof (ret)) | ||||
| 	    eof_detected (true); | ||||
| 	  else | ||||
| 	    eom_detected (true); | ||||
| 	} | ||||
|       else if (is_eom (ret)) | ||||
| 	{ | ||||
| 	  debug_printf ("return -1, set errno to ENOSPC"); | ||||
| 	  set_errno (ENOSPC); | ||||
| 	  goto err; | ||||
| 	} | ||||
|     } | ||||
|  | ||||
|   ulen = (size_t) bytes_read; | ||||
|   return; | ||||
|  | ||||
| err: | ||||
|   ulen = (size_t) -1; | ||||
| } | ||||
|  | ||||
| int | ||||
| fhandler_dev_raw::raw_write (const void *ptr, size_t len) | ||||
| { | ||||
|   DWORD bytes_written = 0; | ||||
|   char *p = (char *) ptr; | ||||
|   int ret; | ||||
|  | ||||
|   /* Checking a previous end of media on tape */ | ||||
|   if (eom_detected ()) | ||||
|     { | ||||
|       set_errno (ENOSPC); | ||||
|       return -1; | ||||
|     } | ||||
|  | ||||
|   /* Invalidate buffer. */ | ||||
|   devbufstart = devbufend = 0; | ||||
|  | ||||
|   if (len > 0) | ||||
|     { | ||||
|       if (!write_file (p, len, &bytes_written, &ret)) | ||||
| 	{ | ||||
| 	  if (!is_eom (ret)) | ||||
| 	    { | ||||
| 	      __seterrno (); | ||||
| 	      return -1; | ||||
| 	    } | ||||
| 	  eom_detected (true); | ||||
| 	  if (!bytes_written) | ||||
| 	    { | ||||
| 	      set_errno (ENOSPC); | ||||
| 	      return -1; | ||||
| 	    } | ||||
| 	} | ||||
|     } | ||||
|   return bytes_written; | ||||
| } | ||||
|  | ||||
| int | ||||
| fhandler_dev_raw::dup (fhandler_base *child) | ||||
| { | ||||
|   int ret = fhandler_base::dup (child); | ||||
|  | ||||
|   if (! ret) | ||||
|   if (!ret) | ||||
|     { | ||||
|       fhandler_dev_raw *fhc = (fhandler_dev_raw *) child; | ||||
|  | ||||
|       fhc->drive_size = drive_size; | ||||
|       fhc->current_position = current_position; | ||||
|       fhc->bytes_per_sector = bytes_per_sector; | ||||
|       fhc->devbufsiz = devbufsiz; | ||||
|       if (devbufsiz > 1L) | ||||
| 	fhc->devbuf = new char [devbufsiz]; | ||||
|       fhc->devbufstart = 0; | ||||
|       fhc->devbufend = 0; | ||||
|       fhc->eom_detected (eom_detected ()); | ||||
|       fhc->eof_detected (eof_detected ()); | ||||
|       fhc->lastblk_to_read (false); | ||||
|     } | ||||
|   return ret; | ||||
| @@ -385,8 +154,6 @@ fhandler_dev_raw::ioctl (unsigned int cmd, void *buf) | ||||
| 		mop.mt_count = op->rd_parm; | ||||
| 		ret = ioctl (MTIOCTOP, &mop); | ||||
| 	      } | ||||
| 	    else if (op->rd_parm % bytes_per_sector) | ||||
| 	      ret = ERROR_INVALID_PARAMETER; | ||||
| 	    else if (devbuf && op->rd_parm < devbufend - devbufstart) | ||||
| 	      ret = ERROR_INVALID_PARAMETER; | ||||
| 	    else if (!devbuf || op->rd_parm != devbufsiz) | ||||
|   | ||||
| @@ -59,7 +59,8 @@ static NO_COPY wincaps wincap_unknown = { | ||||
|   has_extended_priority_class:false, | ||||
|   has_guid_volumes:false, | ||||
|   detect_win16_exe:true, | ||||
|   has_null_console_handler_routine:false | ||||
|   has_null_console_handler_routine:false, | ||||
|   has_disk_ex_ioctls:false | ||||
| }; | ||||
|  | ||||
| static NO_COPY wincaps wincap_95 = { | ||||
| @@ -110,7 +111,8 @@ static NO_COPY wincaps wincap_95 = { | ||||
|   has_extended_priority_class:false, | ||||
|   has_guid_volumes:false, | ||||
|   detect_win16_exe:true, | ||||
|   has_null_console_handler_routine:false | ||||
|   has_null_console_handler_routine:false, | ||||
|   has_disk_ex_ioctls:false | ||||
| }; | ||||
|  | ||||
| static NO_COPY wincaps wincap_95osr2 = { | ||||
| @@ -161,7 +163,8 @@ static NO_COPY wincaps wincap_95osr2 = { | ||||
|   has_extended_priority_class:false, | ||||
|   has_guid_volumes:false, | ||||
|   detect_win16_exe:true, | ||||
|   has_null_console_handler_routine:false | ||||
|   has_null_console_handler_routine:false, | ||||
|   has_disk_ex_ioctls:false | ||||
| }; | ||||
|  | ||||
| static NO_COPY wincaps wincap_98 = { | ||||
| @@ -212,7 +215,8 @@ static NO_COPY wincaps wincap_98 = { | ||||
|   has_extended_priority_class:false, | ||||
|   has_guid_volumes:false, | ||||
|   detect_win16_exe:true, | ||||
|   has_null_console_handler_routine:false | ||||
|   has_null_console_handler_routine:false, | ||||
|   has_disk_ex_ioctls:false | ||||
| }; | ||||
|  | ||||
| static NO_COPY wincaps wincap_98se = { | ||||
| @@ -263,7 +267,8 @@ static NO_COPY wincaps wincap_98se = { | ||||
|   has_extended_priority_class:false, | ||||
|   has_guid_volumes:false, | ||||
|   detect_win16_exe:true, | ||||
|   has_null_console_handler_routine:false | ||||
|   has_null_console_handler_routine:false, | ||||
|   has_disk_ex_ioctls:false | ||||
| }; | ||||
|  | ||||
| static NO_COPY wincaps wincap_me = { | ||||
| @@ -314,7 +319,8 @@ static NO_COPY wincaps wincap_me = { | ||||
|   has_extended_priority_class:false, | ||||
|   has_guid_volumes:false, | ||||
|   detect_win16_exe:true, | ||||
|   has_null_console_handler_routine:false | ||||
|   has_null_console_handler_routine:false, | ||||
|   has_disk_ex_ioctls:false | ||||
| }; | ||||
|  | ||||
| static NO_COPY wincaps wincap_nt3 = { | ||||
| @@ -365,7 +371,8 @@ static NO_COPY wincaps wincap_nt3 = { | ||||
|   has_extended_priority_class:false, | ||||
|   has_guid_volumes:false, | ||||
|   detect_win16_exe:false, | ||||
|   has_null_console_handler_routine:true | ||||
|   has_null_console_handler_routine:true, | ||||
|   has_disk_ex_ioctls:false | ||||
| }; | ||||
|  | ||||
| static NO_COPY wincaps wincap_nt4 = { | ||||
| @@ -416,7 +423,8 @@ static NO_COPY wincaps wincap_nt4 = { | ||||
|   has_extended_priority_class:false, | ||||
|   has_guid_volumes:false, | ||||
|   detect_win16_exe:false, | ||||
|   has_null_console_handler_routine:true | ||||
|   has_null_console_handler_routine:true, | ||||
|   has_disk_ex_ioctls:false | ||||
| }; | ||||
|  | ||||
| static NO_COPY wincaps wincap_nt4sp4 = { | ||||
| @@ -467,7 +475,8 @@ static NO_COPY wincaps wincap_nt4sp4 = { | ||||
|   has_extended_priority_class:false, | ||||
|   has_guid_volumes:false, | ||||
|   detect_win16_exe:false, | ||||
|   has_null_console_handler_routine:true | ||||
|   has_null_console_handler_routine:true, | ||||
|   has_disk_ex_ioctls:false | ||||
| }; | ||||
|  | ||||
| static NO_COPY wincaps wincap_2000 = { | ||||
| @@ -518,7 +527,8 @@ static NO_COPY wincaps wincap_2000 = { | ||||
|   has_extended_priority_class:true, | ||||
|   has_guid_volumes:true, | ||||
|   detect_win16_exe:false, | ||||
|   has_null_console_handler_routine:true | ||||
|   has_null_console_handler_routine:true, | ||||
|   has_disk_ex_ioctls:false | ||||
| }; | ||||
|  | ||||
| static NO_COPY wincaps wincap_xp = { | ||||
| @@ -569,7 +579,8 @@ static NO_COPY wincaps wincap_xp = { | ||||
|   has_extended_priority_class:true, | ||||
|   has_guid_volumes:true, | ||||
|   detect_win16_exe:false, | ||||
|   has_null_console_handler_routine:true | ||||
|   has_null_console_handler_routine:true, | ||||
|   has_disk_ex_ioctls:true | ||||
| }; | ||||
|  | ||||
| static NO_COPY wincaps wincap_2003 = { | ||||
| @@ -620,7 +631,60 @@ static NO_COPY wincaps wincap_2003 = { | ||||
|   has_extended_priority_class:true, | ||||
|   has_guid_volumes:true, | ||||
|   detect_win16_exe:false, | ||||
|   has_null_console_handler_routine:true | ||||
|   has_null_console_handler_routine:true, | ||||
|   has_disk_ex_ioctls:true | ||||
| }; | ||||
|  | ||||
| static NO_COPY wincaps wincap_vista = { | ||||
|   lock_file_highword:UINT32_MAX, | ||||
|   chunksize:0, | ||||
|   shared:FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, | ||||
|   is_winnt:true, | ||||
|   is_server:true, | ||||
|   access_denied_on_delete:false, | ||||
|   has_delete_on_close:true, | ||||
|   has_page_guard:true, | ||||
|   has_security:true, | ||||
|   has_security_descriptor_control:true, | ||||
|   has_get_process_times:true, | ||||
|   has_lseek_bug:false, | ||||
|   has_lock_file_ex:true, | ||||
|   has_signal_object_and_wait:true, | ||||
|   has_eventlog:true, | ||||
|   has_ip_helper_lib:true, | ||||
|   has_set_handle_information:true, | ||||
|   has_set_handle_information_on_console_handles:true, | ||||
|   supports_smp:true, | ||||
|   map_view_of_file_ex_sucks:false, | ||||
|   altgr_is_ctrl_alt:true, | ||||
|   has_physical_mem_access:true, | ||||
|   has_working_copy_on_write:true, | ||||
|   share_mmaps_only_by_name:false, | ||||
|   virtual_protect_works_on_shared_pages:true, | ||||
|   has_hard_links:true, | ||||
|   can_open_directories:true, | ||||
|   has_move_file_ex:true, | ||||
|   has_negative_pids:false, | ||||
|   has_unreliable_pipes:false, | ||||
|   has_named_pipes:true, | ||||
|   has_try_enter_critical_section:true, | ||||
|   has_raw_devices:true, | ||||
|   has_valid_processorlevel:true, | ||||
|   has_64bit_file_access:true, | ||||
|   has_process_io_counters:true, | ||||
|   supports_reading_modem_output_lines:true, | ||||
|   needs_memory_protection:true, | ||||
|   pty_needs_alloc_console:true, | ||||
|   has_terminal_services:true, | ||||
|   has_switch_to_thread:true, | ||||
|   cant_debug_dll_entry:false, | ||||
|   has_ioctl_storage_get_media_types_ex:true, | ||||
|   start_proc_suspended:false, | ||||
|   has_extended_priority_class:true, | ||||
|   has_guid_volumes:true, | ||||
|   detect_win16_exe:false, | ||||
|   has_null_console_handler_routine:true, | ||||
|   has_disk_ex_ioctls:true | ||||
| }; | ||||
|  | ||||
| wincapc wincap; | ||||
| @@ -676,6 +740,11 @@ wincapc::init () | ||||
| 		    caps = &wincap_2003; | ||||
| 		} | ||||
| 	      break; | ||||
| 	    case 6: | ||||
| 	      os = "NT"; | ||||
| 	      has_osversioninfoex = true; | ||||
| 	      caps = &wincap_vista; | ||||
| 	      break; | ||||
| 	    default: | ||||
| 	      os = "??"; | ||||
| 	      caps = &wincap_unknown; | ||||
|   | ||||
| @@ -61,6 +61,7 @@ struct wincaps | ||||
|   unsigned has_guid_volumes				: 1; | ||||
|   unsigned detect_win16_exe				: 1; | ||||
|   unsigned has_null_console_handler_routine		: 1; | ||||
|   unsigned has_disk_ex_ioctls				: 1; | ||||
| }; | ||||
|  | ||||
| class wincapc | ||||
| @@ -126,6 +127,7 @@ public: | ||||
|   bool	IMPLEMENT (has_guid_volumes) | ||||
|   bool	IMPLEMENT (detect_win16_exe) | ||||
|   bool	IMPLEMENT (has_null_console_handler_routine) | ||||
|   bool	IMPLEMENT (has_disk_ex_ioctls) | ||||
|  | ||||
| #undef IMPLEMENT | ||||
| }; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user