在 Windows 上将原始数据写入物理磁盘(闪存驱动器)失败并显示“错误的文件描述符” - Python

Mia*_*ola 5 python windows io file-io

我正在尝试对 USB 闪存驱动器执行直接数据读取和写入作为 Windows 上的物理驱动器(如果重要,则为 10)。我正在使用 Python 来做到这一点。

我遵循了以下讨论:

使用 python 和 windows 获得对原始设备的写入访问权限

我遇到了kcstrom在那个问题中遇到的同样问题。我得到一个

    Traceback (most recent call last):
    File "C:\script.py", line 49, in <module>
    disk.write(data)
    IOError: [Errno 9] Bad file descriptor
Run Code Online (Sandbox Code Playgroud)

阅读和寻找工作应有尽有,读取的数据是正确的。

到目前为止我所知道的

  1. 处理驱动器应该在扇区大小的读/写/搜索中完成。
  2. 磁盘必须以“rb+”模式打开。
  3. 同时使用 \\.\L: 和 \\.\PhysicalDriveN 会产生相同的结果。
  4. 该脚本必须在管理员权限下运行。
  5. 卸载驱动器并尝试访问 \\.\PhysicalDriveN 文件 - 即使以管理员身份运行,“权限被拒绝”。

重现错误:(警告:此代码可能损坏物理驱动器,仅当您知道自己在做什么时才运行)

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)
Run Code Online (Sandbox Code Playgroud)

我不知道这是权限问题还是我打开驱动器的方式有问题。

Ery*_*Sun 5

根据 MSDN 技术说明“阻止对卷和磁盘的直接写入操作”

如果文件系统没有挂载,或者如果:

  • 被写入的扇区是引导扇区。
  • 被写入的扇区驻留在文件系统空间之外。
  • 文件系统已通过请求独占写访问隐式锁定。
  • 文件系统已通过发送锁定/卸载请求明确锁定。

....

在以下情况下,磁盘句柄上的写操作将成功:

  • 写入的扇区不属于文件系统。
  • 正在写入的扇区属于明确锁定的已安装文件系统。
  • 写入的扇区属于未安装的文件系统或卷没有文件系统。

这是一个用于锁定卷的简单上下文管理器。它使用来自 PyWin32的win32filewinoctlcon模块。

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')
Run Code Online (Sandbox Code Playgroud)