tags:

views:

61

answers:

1
#!/usr/bin/env python
# -*- coding: utf-8 -*-
########## THIS NOW WORKS! ##########

UNSUITABLE_ENVIRONMENT_ERROR = \ 
    "This program requires at least Python 2.6 and Linux"

import sys 
import struct
import os
from array import array

# +++ Check environment
try:
    import platform # Introduced in Python 2.3
except ImportError:
    print >>sys.stderr, UNSUITABLE_ENVIRONMENT_ERROR
if platform.system() != "Linux":
    print >>sys.stderr, UNSUITABLE_ENVIRONMENT_ERROR
if platform.python_version_tuple()[:2] < (2, 6): 
    print >>sys.stderr, UNSUITABLE_ENVIRONMENT_ERROR

# --- Check environment

HDIO_GETGEO = 0x301 # Linux
import fcntl

def get_disk_geometry(fd):
    geometry = array('c',"XXXXXXXX")
    fcntl.ioctl(fd, HDIO_GETGEO, geometry, True)
    heads, sectors, cylinders, start = \ 
        struct.unpack("BBHL",geometry.tostring())
    return { 'heads' : heads, 'cylinders': cylinders, 'sectors': sectors, "start": start }

from pprint import pprint
fd=os.open("/dev/sdb", os.O_RDWR)
pprint(get_disk_geometry(fd))
A: 

Nobody seems to be able to tell me why you can't do this, but you can do it with ctypes so it doesn't really matter.

#!/usr/bin/env python
from ctypes import *
import os
from pprint import pprint

libc = CDLL("libc.so.6")
HDIO_GETGEO = 0x301 # Linux

class HDGeometry(Structure):
    _fields_ = (("heads", c_ubyte),
                ("sectors", c_ubyte),
                ("cylinders", c_ushort),
                ("start", c_ulong))

    def __repr__(self):
        return """Heads: %s, Sectors %s, Cylinders %s, Start %s""" % (
                self.heads, self.sectors, self.cylinders, self.start)

def get_disk_geometry(fd):
    """ Returns the heads, sectors, cylinders and start of disk as rerpoted by
    BIOS. These us usually bogus, but we still need them"""

    buffer = create_string_buffer(sizeof(HDGeometry))
    g = cast(buffer, POINTER(HDGeometry))
    result = libc.ioctl(fd, HDIO_GETGEO, byref(buffer))
    assert result == 0
    return g.contents

if __name__ == "__main__":
    fd = os.open("/dev/sdb", os.O_RDWR)
    print repr(get_disk_geometry(fd))
Using `import *` pollutes your namespace, making programs harder to read and debug. Consider using `import extralongmodulename as e` if you require conciseness.
Mike Graham
ctypes is the only module I ever do it with and I agree, but ctypes is a general pain in the ass. I suppose importing it as C or something would be ok.