2010-05-05 18 views
3

J'ai un script Python qui lit un fichier (généralement issu d'un support optique) marquant les secteurs illisibles, pour permettre une nouvelle tentative de lecture desdits secteurs illisibles sur un lecteur optique différent.Taille de la requête du fichier périphérique en Python

J'ai découvert que mon script ne fonctionne pas avec les périphériques bloc (par exemple/dev/sr0), afin de créer une copie du système de fichiers ISO9660/UDF contenu, car os.stat().st_size est zéro. L'algorithme doit actuellement connaître la taille du fichier à l'avance; Je peux changer cela, mais le problème (connaître la taille du périphérique de bloc) reste, et il n'y a pas de réponse ici, alors j'ouvre cette question.

Je suis au courant des deux liés SO questions suivantes:

Par conséquent, , Je demande: en Python, comment puis-je obtenir la taille d'un fichier de périphérique de bloc?

Répondre

6

Le « plus propre » (c.-à-ne dépend pas de volumes externes et plus réutilisable) solution Python que je suis arrivé, est d'ouvrir le fichier et le chercher à la fin, retour le fichier offset:

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) 
+1

Puisqu'il n'y avait pas d'autres réponses après 2 semaines, j'ai choisi ma propre réponse. – tzot

0

Essayer d'adapter de l'autre réponse:

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

Je n'ai pas un ordinateur approprié à portée de main pour tester. Je serais curieux de savoir si cela fonctionne :)

+0

Je l'ai essayé avec 'f = open' et' fd = os.open' (puisque 'fcntl.ioctl' requiert un descripteur de fichier, bien qu'il puisse appeler' .fileno() 'sur un objet fichier Python). Dans les deux cas, 'fcntl.ioctl' a déclenché' IOError: [Errno 14] Bad address'. – tzot

4

solution ioctl spécifiques de Linux:

import fcntl 
import struct 

device_path = '/dev/sr0' 

req = 0x80081272 # BLKGETSIZE64, result is bytes as unsigned 64-bit integer (uint64) 
buf = ' ' * 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' 

d'autres unix auront des valeurs différentes pour req, buf, fmt bien sûr.