¿Es posible obtener acceso de escritura a dispositivos en bruto utilizando Python con Windows?

Esto es una especie de seguimiento a esta pregunta . Quiero saber si puede acceder a dispositivos sin formato (es decir, \\.\PhysicalDriveN ) en modo de escritura y, si este es el caso, cómo.

Usando Linux, el acceso de escritura se puede lograr simplemente usando, por ejemplo, open("/dev/sdd", "w+") (siempre que el script se ejecute con permisos de root). Supongo que Mac OS se comporta de manera similar (con /dev/diskN como archivo de entrada).

Cuando se intenta el mismo comando en Windows (con la ruta correspondiente), falla con el siguiente error:

 IOError: [Errno 22] invalid mode ('w+') or filename: '\\\\.\\PhysicalDrive3' 

Sin embargo, cuando se intenta leer desde PhysicalDrive, funciona (incluso se leen los datos correctos). El shell se está ejecutando con permisos de administrador bajo Windows 7.

¿Hay alguna otra forma de realizar esta tarea usando python mientras se mantiene el script lo más independiente de la plataforma posible?

Editar:

Miré un poco más allá de los métodos que Python proporciona para el manejo de archivos y tropecé con os.open . Al abrir PhysicalDrive con os.open(drive_string, os.O_WRONLY|os.O_BINARY) no se os.open(drive_string, os.O_WRONLY|os.O_BINARY) ningún error. Hasta ahora tan bueno. Ahora tengo la opción de escribir directamente en este descriptor de archivo usando os.write , o usar os.fdopen para obtener un objeto de archivo y escribir en él de forma regular. Lamentablemente, ninguna de estas posibilidades funciona. En el primer caso ( os.write() ), obtengo esto:

 >>> os.write(os.open("\\\\.\\PhysicalDrive3", os.O_WRONLY|os.O_BINARY), "test") Traceback (most recent call last): File "", line 1, in  OSError: [Errno 22] Invalid argument 

En el segundo caso, puedo crear un objeto de archivo con permisos de escritura, pero la escritura en sí falla (bueno, después de aplicar su ejecución usando .flush() ):

 >>> g = os.fdopen(os.open("\\\\.\\PhysicalDrive3", os.O_WRONLY|os.O_BINARY), "wb") >>> g.write("test") >>> g.flush() Traceback (most recent call last): File "", line 1, in  IOError: [Errno 22] Invalid argument 

Como eryksun y agf señalaron en los comentarios (pero al principio no lo obtuve), la solución es bastante simple: tienes que abrir el dispositivo en el modo rb+ , que abre el dispositivo para la actualización (como he encontrado ahora …) sin intentar reemplazarlo con un nuevo archivo (que no funcionaría porque el archivo es en realidad una unidad física).

Al escribir, debe escribir siempre un sector completo a la vez (es decir, múltiplos de 512 bytes), de lo contrario falla.

Además, el .seek() también puede saltar solo por sectores. Si intenta buscar una posición dentro de un sector (por ejemplo, la posición 621 ), el objeto de archivo saltará al principio del sector donde se encuentra su posición solicitada (es decir, al principio del segundo sector, byte 512 ).

Posiblemente en Win 7 tenga que hacer algo más extremo, como bloquear el (los) volumen (s) para el disco de antemano con DeviceIoControl (hVol, FSCTL_LOCK_VOLUME, …)

En Win 7 no tienes que hacer eso; abrir y escribir con el modo ‘rb +’ funciona bien.