简体   繁体   English

Python中查询块设备文件的大小

[英]Query size of block device file in Python

I have a Python script that reads a file (typically from optical media) marking the unreadable sectors, to allow a re-attempt to read said unreadable sectors on a different optical reader.我有一个 Python 脚本,它读取标记不可读扇区的文件(通常来自光学介质),以允许重新尝试在不同的光学读取器上读取所述不可读扇区。

I discovered that my script does not work with block devices (eg /dev/sr0), in order to create a copy of the contained ISO9660/UDF filesystem, because os.stat().st_size is zero.我发现我的脚本不适用于块设备(例如 /dev/sr0),以便创建包含的 ISO9660/UDF 文件系统的副本,因为os.stat().st_size为零。 The algorithm currently needs to know the filesize in advance;该算法目前需要提前知道文件大小; I can change that, but the issue (of knowing the block device size) remains, and it's not answered here, so I open this question.我可以改变它,但问题(知道块设备大小)仍然存在,这里没有回答,所以我打开这个问题。

I am aware of the following two related SO questions:我知道以下两个相关的 SO 问题:

Therefore, I'm asking: in Python, how can I get the file size of a block device file?因此,我问:在 Python 中,如何获取块设备文件的文件大小?

The “most clean” (ie not dependent on external volumes and most reusable) Python solution I've reached, is to open the device file and seek at the end, returning the file offset:我已经达到的“最干净”(即不依赖于外部卷且最可重用)的 Python 解决方案是打开设备文件并在末尾查找,返回文件偏移量:

def get_file_size(filename):
    "Get the file size by seeking at end"
    fd= os.open(filename, os.O_RDONLY)
    try:
        return os.lseek(fd, 0, os.SEEK_END)
    finally:
        os.close(fd)

Linux-specific ioctl-based solution: Linux 特有的基于 ioctl 的解决方案:

import fcntl
import struct

device_path = '/dev/sr0'

req = 0x80081272 # BLKGETSIZE64, result is bytes as unsigned 64-bit integer (uint64)
buf = b' ' * 8
fmt = 'L'

with open(device_path) as dev:
    buf = fcntl.ioctl(dev.fileno(), req, buf)
bytes = struct.unpack('L', buf)[0]

print device_path, 'is about', bytes / (1024 ** 2), 'megabytes'

Other unixes will have different values for req, buf, fmt of course.当然,其他 unix 对 req、buf、fmt 会有不同的值。

Another possible solution is另一种可能的解决方案是

def blockdev_size(path):
    """Return device size in bytes.
    """
    with open(path, 'rb') as f:
        return f.seek(0, 2) or f.tell()

or f.tell() part is there for Python 2 portability's sake — file.seek() returns None in Python 2. or f.tell()部分是为了 Python 2 的可移植性而存在的 — file.seek()在 Python 2 中返回 None。

Magic constant 2 may be substituted with io.SEEK_END .魔术常数2可以用io.SEEK_END

In Linux, there is /sys/block/${dev}/size that can be read even without sudo.在 Linux 中,即使没有 sudo 也可以读取/sys/block/${dev}/size To get the size of /dev/sdb simply do:要获取/dev/sdb的大小,只需执行以下操作:

print( 512 * int(open('/sys/block/sdb/size','r').read()) )

See also https://unix.stackexchange.com/a/52219/384116另见https://unix.stackexchange.com/a/52219/384116

Trying to adapt from the other answer:试图适应另一个答案:

import fcntl
c = 0x00001260 ## check man ioctl_list, BLKGETSIZE
f = open('/dev/sr0', 'ro')
s = fcntl.ioctl(f, c)
print s

I don't have a suitable computer at hand to test this.我手头没有合适的计算机来测试这个。 I'd be curious to know if it works :)我很想知道它是否有效:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM