MiaoHatola
MiaoHatola

Reputation: 185

Writing raw data to physical disk (flash drive) fails with "Bad file descriptor" on windows - Python

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:

  1. Handling the drive should be done in sector sized reads/writes/seeks.
  2. The disk must be opened with 'rb+' mode.
  3. Using both \\.\L: and \\.\PhysicalDriveN produce the same results.
  4. The script must run under administrator privileges.
  5. Unmounting the drive and trying to access the \\.\PhysicalDriveN file - "Permission Denied" even when running as admin.

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

Answers (1)

Eryk Sun
Eryk Sun

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

Related Questions