Reputation: 185
I am trying to perform direct data reading and writing to a USB flash drive as a physical drive on windows (10 if it matters). I am using Python to do that.
I have followed the following discussion:
get writing access to raw devices using python with windows
I ran into the same problem kcstrom had in that question. I get a
Traceback (most recent call last):
File "C:\script.py", line 49, in <module>
disk.write(data)
IOError: [Errno 9] Bad file descriptor
Reading and seeking work as they should, and the data read is correct.
What I know so far:
To reproduce the error: (WARNING: THIS CODE CAN CORRUPT PHYSICAL DRIVES, RUN ONLY IF YOU KNOW WHAT YOU ARE DOING)
SOME_OFFSET = 123123
SOME_SIZE = 100
# replace L with the drive letter
disk = open('\\\\.\\L:','r+b')
# or use: (replace N with the drive number)
# disk = open('\\\\.\\PhysicalDriveN','r+b')
disk.seek(SOME_OFFSET*512)
data = disk.read(SOME_SIZE*512)
#modify data...
disk.seek(SOME_OFFSET*512)
disk.write(data)
I can't figure out if this is a permission issue or a problem with how I opened the drive.
Upvotes: 7
Views: 3565
Reputation: 34290
According to the MSDN technical note "Blocking Direct Write Operations to Volumes and Disks":
Write operations on a DASD volume handle will succeed if the file system is not mounted, or if:
- The sectors being written to are the boot sectors.
- The sectors being written to reside outside file system space.
- The file system has been locked implicitly by requesting exclusive write access.
- The file system has been locked explicitly by sending down a lock/dismount request.
....
Write operations on a disk handle will succeed if:
- The sectors being written to do not fall within a file system.
- The sectors being written to fall within a mounted file system that is locked explicitly.
- The sectors being written to fall within a file system that is not mounted or the volume has no file system.
Here's a simple context manager to lock a volume. It uses the win32file
and winoctlcon
modules from PyWin32.
import msvcrt
import win32file
import winioctlcon
import contextlib
@contextlib.contextmanager
def lock_volume(vol):
hVol = msvcrt.get_osfhandle(vol.fileno())
win32file.DeviceIoControl(hVol, winioctlcon.FSCTL_LOCK_VOLUME,
None, None)
try:
yield vol
finally:
try:
vol.flush()
finally:
win32file.DeviceIoControl(hVol, winioctlcon.FSCTL_UNLOCK_VOLUME,
None, None)
if __name__ == '__main__':
VOLUME_PATH = r'\\.\E:'
OFFSET = 123123
SIZE = 100
with open(VOLUME_PATH, 'r+b') as disk:
with lock_volume(disk):
disk.seek(OFFSET * 512)
data = disk.read(SIZE * 512)
disk.seek(OFFSET * 512)
disk.write(data)
input('press enter to unlock the volume')
Upvotes: 7