Hello Antonio,

Antonio Diaz Diaz wrote:
Christian Franke wrote:
the attached patch adds device_id() for Cygwin. Tested with 32- and 64-bit Cygwin.
Should be safe to include in 1.21 as no other platform is affected.

Thanks for the patch.

The patch is mostly ok but, isn't there a safer way of implementing this for Cygwin? I don't like neither the use of an union nor the unverified access to the 'raw' member in the union ('data.raw[data.desc.VendorIdOffset]', for example). Most probably this will cause problems with '-fstrict-aliasing', or even an invalid memory access.

New attached new patch avoids the union, does strict index checks and ensures zero termination. It now also allows that an ATA IDENTIFY string is only in VendorId or ProductId which occasionally happened with some older drives.

Tested with g++ 4.9.3 and clang++ 3.5.2.

BTW: I guess both approaches (char buffer + cast to *struct, union of buf + struct) are safe:
"A character type may alias any other type."
"Even with -fstrict-aliasing, type-punning is allowed, provided the memory is accessed through the union type."
https://gcc.gnu.org/onlinedocs/gcc-4.9.3/gcc/Optimize-Options.html#index-fstrict-aliasing-926

Best regards,
Christian

2015-12-18  Christian Franke  <[email protected]>

        * non_posix.cc:  Add device_id() for Cygwin.

diff --git a/non_posix.cc b/non_posix.cc
index 480c71d..7d7217f 100644
--- a/non_posix.cc
+++ b/non_posix.cc
@@ -56,6 +56,57 @@ const char * device_id( const int fd )
   return id_str.c_str();
   }
 
+#elif defined(__CYGWIN__)
+
+#include <cstddef>
+#include <io.h>
+#include <windows.h>
+
+const char * device_id( const int fd )
+  {
+  HANDLE h = (HANDLE) _get_osfhandle( fd );
+  if( h == INVALID_HANDLE_VALUE )
+    return 0;
+
+  STORAGE_PROPERTY_QUERY query =
+    { StorageDeviceProperty, PropertyStandardQuery, { 0 } };
+  char buf[256] = "";
+  DWORD size = 0;
+
+  if( !DeviceIoControl( h, IOCTL_STORAGE_QUERY_PROPERTY, &query, sizeof(query),
+                        &buf, sizeof(buf)-1, &size, (LPOVERLAPPED)0 ) )
+    return 0;
+
+  const STORAGE_DEVICE_DESCRIPTOR * const pdesc =
+    reinterpret_cast< STORAGE_DEVICE_DESCRIPTOR * >( buf );
+  const unsigned first =
+    offsetof( STORAGE_DEVICE_DESCRIPTOR, RawDeviceProperties );
+
+  static std::string id_str;
+  if( first <= pdesc->VendorIdOffset && pdesc->VendorIdOffset < size )
+    id_str = &buf[pdesc->VendorIdOffset];
+  if( first <= pdesc->ProductIdOffset && pdesc->ProductIdOffset < size )
+    {
+    if(    pdesc->BusType != BusTypeAta
+        && pdesc->BusType != 0x0b ) // BusTypeSata
+      id_str += ' ';
+    id_str += &buf[pdesc->ProductIdOffset];
+    }
+  sanitize_string( id_str );
+  if( id_str.empty() )
+    return 0;
+
+  if( first <= pdesc->SerialNumberOffset && pdesc->SerialNumberOffset < size )
+    {
+    std::string id_serial( &buf[pdesc->SerialNumberOffset] );
+    sanitize_string( id_serial );
+    if ( !id_serial.empty() )
+      { id_str += "::"; id_str += id_serial; }
+    }
+
+  return id_str.c_str();
+  }
+
 #else                          // use linux by default
 #include <linux/hdreg.h>
 
_______________________________________________
Bug-ddrescue mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/bug-ddrescue

Reply via email to