将原始数据写入物理磁盘(闪存驱动器)失败,其中包含错误的文件描述符"在Windows上 - Python

时间:2016-10-25 12:11:15

标签: python windows file-io io

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

我遵循了以下讨论:

get writing access to raw devices using python with windows

我遇到了问题中kcstrom遇到的同样问题。我得到了

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

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

到目前为止我所知道的

  1. 处理驱动器应以扇区大小的读/写/搜索方式完成。
  2. 必须使用&rbsp +&#39;打开磁盘。模式。
  3. 同时使用\\。\ L:和\\。\ PhysicalDriveN会产生相同的结果。
  4. 脚本必须以管理员权限运行。
  5. 卸载驱动器并尝试访问\\。\ PhysicalDriveN文件 - &#34;权限被拒绝&#34;即使以管理员身份运行。
  6. 重现错误:(警告:此代码可能会破坏物理驱动,只有在您知道要做什么的情况下才能运行)

    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)
    

    我无法弄清楚这是许可问题还是我打开硬盘的问题。

1 个答案:

答案 0 :(得分:3)

根据MSDN技术说明"Blocking Direct Write Operations to Volumes and Disks"

  

如果文件,DASD卷句柄上的写操作将成功   系统未安装,或者如果:

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

....

     

如果出现以下情况,磁盘句柄上的写操作将成功:

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

这是一个锁定卷的简单上下文管理器。它使用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')