Why can't I in python call HDIO_GETGEO?
Question: 
    #!/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))
    


Answer: 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))
    

