diff --git a/Changelog b/Changelog
--- a/Changelog
+++ b/Changelog
@@ -1,3 +1,10 @@
+1.8.12 [2024-08-02]
+
+* Add flag "use-hdf5-serial" to switch between "hdf5" and "hdf5-serial" as a pkgconfig dependency
+* Add pipeline ensuring the project compiles and the tests run with ghcup and ghc 9.0, 9.2, 9.4 and 9.6.
+* Fixes to support different versions of hdf5 simultaneously
+* Add upper version bounds to conform wiht the Haskell PVP document
+
 1.8.11 [2023-10-10]
 ------
 
diff --git a/cbits/H5E_inline.c b/cbits/H5E_inline.c
--- a/cbits/H5E_inline.c
+++ b/cbits/H5E_inline.c
@@ -26,7 +26,9 @@
 BC_INLINE_(H5E_RS,                  hid_t)
 BC_INLINE_(H5E_HEAP,                hid_t)
 BC_INLINE_(H5E_OHDR,                hid_t)
+#if !H5_VERSION_GE(1,8,14)
 BC_INLINE_(H5E_ATOM,                hid_t)
+#endif
 BC_INLINE_(H5E_ATTR,                hid_t)
 BC_INLINE_(H5E_NONE_MAJOR,          hid_t)
 BC_INLINE_(H5E_IO,                  hid_t)
@@ -120,7 +122,9 @@
 BC_INLINE_(H5E_TRUNCATED,           hid_t)
 BC_INLINE_(H5E_MOUNT,               hid_t)
 
+#if !H5_VERSION_GE(1,8,14)
 BC_INLINE_(H5E_BADATOM,             hid_t)
+#endif
 BC_INLINE_(H5E_BADGROUP,            hid_t)
 BC_INLINE_(H5E_CANTREGISTER,        hid_t)
 BC_INLINE_(H5E_CANTINC,             hid_t)
diff --git a/cbits/H5FD_inline.c b/cbits/H5FD_inline.c
--- a/cbits/H5FD_inline.c
+++ b/cbits/H5FD_inline.c
@@ -1,4 +1,7 @@
 #include <H5FDpublic.h>
+#if H5_VERSION_GE(1,14,0)
+#include <H5FDdevelop.h>
+#endif
 
 #include <string.h>
 
diff --git a/hdf5.cabal b/hdf5.cabal
--- a/hdf5.cabal
+++ b/hdf5.cabal
@@ -1,5 +1,5 @@
 name:                   hdf5
-version:                1.8.11
+version:                1.8.12
 stability:              provisional
 
 cabal-version:          >= 1.10
@@ -23,6 +23,11 @@
   type: git
   location: git://github.com/picca/hs-hdf5.git
 
+flag use-hdf5-serial
+  default: False
+  manual: True
+  description: Use Debian's hdf5-serial as a dependency instead of plain hdf5
+
 Library
   hs-source-dirs:       src
   default-language:     Haskell2010
@@ -30,7 +35,6 @@
   default-extensions:   ForeignFunctionInterface
 
   ghc-options:          -Wall
-  cc-options:           -Wno-format
   exposed-modules:      Bindings.HDF5
                       , Bindings.HDF5.Attribute
                       , Bindings.HDF5.Raw
@@ -104,18 +108,21 @@
 
   include-dirs:         include
 
-  build-depends:        base >= 3 && < 5
-                      , bindings-DSL
-                      , bytestring
-                      , libffi
-                      , lifted-base
-                      , monad-control
-                      , primitive
-                      , tagged
-                      , vector
-                      , transformers
+  build-depends:        base >= 3 && < 5,
+                        bindings-DSL >= 1.0.25 && < 1.1,
+                        bytestring >= 0.10.0 && < 0.12,
+                        libffi >= 0.1 && < 0.3,
+                        lifted-base >= 0.2.3 && < 0.3,
+                        monad-control >= 1.0.3 && < 1.1,
+                        transformers >= 0.5.0 && < 0.7,
+                        primitive >= 0.7.0 && < 0.9,
+                        tagged >= 0.8.0 && < 0.9,
+                        vector >= 0.12.0 && < 0.14
 
-  pkgconfig-depends:    hdf5-serial, libffi
+  if flag(use-hdf5-serial)
+    pkgconfig-depends: hdf5-serial
+  else
+    pkgconfig-depends: hdf5
 
 
 test-suite hdf5-test
diff --git a/src/Bindings/HDF5/Dataspace.hs b/src/Bindings/HDF5/Dataspace.hs
deleted file mode 100644
--- a/src/Bindings/HDF5/Dataspace.hs
+++ /dev/null
@@ -1,372 +0,0 @@
-{-# LANGUAGE GeneralizedNewtypeDeriving #-}
-module Bindings.HDF5.Dataspace
-    ( Dataspace
-    , DataspaceClass(..)
-    , SelectionOperator(..)
-    , SelectionType(..)
-
-    , createDataspace
-    , createSimpleDataspace
-    , createExpandableDataspace
-
-    , copyDataspace
-
-    , closeDataspace
-
-    , encodeDataspace
-    , decodeDataspace
-
-    , getSimpleDataspaceExtentNPoints
-    , getSimpleDataspaceExtentNDims
-    , getSimpleDataspaceExtent
-
-    , isSimpleDataspace
-
-    , getDataspaceSelectionNPoints
-
-    , selectHyperslab
-    , selectElements
-
-    , getSimpleDataspaceExtentType
-
-    , setDataspaceExtentNone
-    , copyDataspaceExtent
-    , dataspaceExtentsEqual
-
-    , selectAll
-    , selectNone
-
-    , offsetSimpleDataspaceSelection
-
-    , selectionValid
-
-    , getHyperslabSelection
-    , getHyperslabSelectionNBlocks
-    , getHyperslabSelectionBlockList
-
-    , getElementSelection
-    , getElementSelectionNPoints
-    , getElementSelectionPointList
-
-    , getSelectionBounds
-
-    , getSelectionType
-    ) where
-
-import Bindings.HDF5.Core
-import Bindings.HDF5.Error
-import Bindings.HDF5.Object
-import Bindings.HDF5.Raw.H5I
-import Bindings.HDF5.Raw.H5S
-import Control.Exception (assert)
-import Control.Monad
-import qualified Data.ByteString as BS
-import qualified Data.ByteString.Unsafe as BS
-import Data.List
-import Data.Maybe
-import Data.Tagged
-import qualified Data.Vector as V
-import qualified Data.Vector.Storable as SV
-import Foreign hiding (And, Xor)
-import Foreign.C
-import Foreign.Ptr.Conventions
-
-newtype Dataspace = Dataspace HId_t
-    deriving (Eq, HId, FromHId, HDFResultType)
-
-instance Object Dataspace where
-    staticObjectType = Tagged (Just DataspaceObj)
-
-data DataspaceClass
-    = Scalar
-    | Simple
-    | Null
-    deriving (Eq, Ord, Enum, Bounded, Read, Show)
-
-rawDataspaceClass :: DataspaceClass -> H5S_class_t
-rawDataspaceClass Scalar = h5s_SCALAR
-rawDataspaceClass Simple = h5s_SIMPLE
-rawDataspaceClass Null   = h5s_NULL
-
-dataspaceClass :: H5S_class_t -> DataspaceClass
-dataspaceClass c
-    | c == h5s_SCALAR   = Scalar
-    | c == h5s_SIMPLE   = Simple
-    | c == h5s_NULL     = Null
-    | otherwise         = error ("unknown dataspace class: " ++ show c)
-
-createDataspace :: DataspaceClass -> IO Dataspace
-createDataspace cls =
-    fmap Dataspace $
-        withErrorCheck $
-            h5s_create (rawDataspaceClass cls)
-
-createSimpleDataspace :: [HSize] -> IO Dataspace
-createSimpleDataspace dims =
-    fmap Dataspace $
-        withErrorCheck $
-            withInList (map hSize dims) $ \idims ->
-                h5s_create_simple n idims (InArray nullPtr)
-    where n = genericLength dims
-
-createExpandableDataspace :: [(HSize, Maybe HSize)] -> IO Dataspace
-createExpandableDataspace dims =
-    fmap Dataspace $
-        withErrorCheck $
-            withInList (map hSize dimSizes) $ \idimSizes ->
-                withInList (map (maybe h5s_UNLIMITED hSize) dimLimits) $ \idimLimits ->
-                    h5s_create_simple n idimSizes idimLimits
-    where
-        n = genericLength dims
-        (dimSizes, dimLimits) = unzip dims
-
-copyDataspace :: Dataspace -> IO Dataspace
-copyDataspace (Dataspace space_id) =
-    fmap Dataspace $
-        withErrorCheck $
-            h5s_copy space_id
-
-closeDataspace :: Dataspace -> IO ()
-closeDataspace (Dataspace space_id) =
-    withErrorCheck_ $
-        h5s_close space_id
-
-encodeDataspace :: Dataspace -> IO BS.ByteString
-encodeDataspace (Dataspace space_id) =
-    withOutByteString $ \buf bufSz ->
-        withInOut_ bufSz $ \ioBufSz ->
-            withErrorCheck_ $
-                h5s_encode space_id buf ioBufSz
-
-decodeDataspace :: BS.ByteString -> IO Dataspace
-decodeDataspace bs = BS.unsafeUseAsCString bs $ \buf ->
-    fmap Dataspace $
-        withErrorCheck $
-            h5s_decode (InArray buf)
-
-getSimpleDataspaceExtentNPoints :: Dataspace -> IO HSize
-getSimpleDataspaceExtentNPoints (Dataspace space_id) =
-    fmap fromIntegral $
-        withErrorWhen (< 0) $
-            h5s_get_simple_extent_npoints space_id
-
-getSimpleDataspaceExtentNDims :: Dataspace -> IO CInt
-getSimpleDataspaceExtentNDims (Dataspace space_id) =
-    withErrorWhen (< 0) $
-        h5s_get_simple_extent_ndims space_id
-
-getSimpleDataspaceExtent :: Dataspace -> IO ([HSize], [Maybe HSize])
-getSimpleDataspaceExtent space@(Dataspace space_id) = do
-    n <- getSimpleDataspaceExtentNDims space
-
-    (dims, (maxDims, n')) <-
-        withOutList (fromIntegral n) $ \dims ->
-            withOutList (fromIntegral n) $ \maxDims ->
-                withErrorWhen (< 0) $
-                    h5s_get_simple_extent_dims space_id dims maxDims
-
-    assert (n==n') $ return
-        ( map HSize dims
-        , [ if d == h5s_UNLIMITED then Nothing else Just (HSize d) | d <- maxDims]
-        )
-
-isSimpleDataspace :: Dataspace -> IO Bool
-isSimpleDataspace (Dataspace space_id) =
-    htriToBool $
-        h5s_is_simple space_id
-
-getDataspaceSelectionNPoints :: Dataspace -> IO HSize
-getDataspaceSelectionNPoints (Dataspace space_id) =
-    fmap fromIntegral $
-        withErrorWhen (< 0) $
-            h5s_get_select_npoints space_id
-
-data SelectionOperator
-    = Set
-    | Or
-    | And
-    | Xor
-    | NotB
-    | NotA
-    | Append
-    | Prepend
-    deriving (Eq, Ord, Enum, Bounded, Read, Show)
-
-rawSelectionOperator :: SelectionOperator -> H5S_seloper_t
-rawSelectionOperator Set     = h5s_SELECT_SET
-rawSelectionOperator Or      = h5s_SELECT_OR
-rawSelectionOperator And     = h5s_SELECT_AND
-rawSelectionOperator Xor     = h5s_SELECT_XOR
-rawSelectionOperator NotB    = h5s_SELECT_NOTB
-rawSelectionOperator NotA    = h5s_SELECT_NOTA
-rawSelectionOperator Append  = h5s_SELECT_APPEND
-rawSelectionOperator Prepend = h5s_SELECT_PREPEND
-
-selectHyperslab :: Dataspace -> SelectionOperator -> [(HSize, Maybe HSize, HSize, Maybe HSize)] -> IO ()
-selectHyperslab space@(Dataspace space_id) oper hyperSlab = do
-    nDims <- getSimpleDataspaceExtentNDims space
-
-    when (length hyperSlab /= fromIntegral nDims)
-        (fail "selectHyperslab: the given hyperslab has the wrong number of dimensions for this dataspace")
-
-    withErrorCheck_ $
-        withInList' start $ \istart ->
-            maybe withNull withInList' stride $ \istride ->
-                withInList' count $ \icount ->
-                    maybe withNull withInList' block $ \iblock ->
-                        h5s_select_hyperslab space_id (rawSelectionOperator oper) istart istride icount iblock
-    where
-        (start, mbStrides, count, mbBlocks) = unzip4 hyperSlab
-        stride
-            | any isJust mbStrides  = Just (map (fromMaybe 1) mbStrides)
-            | otherwise             = Nothing
-        block
-            | any isJust mbBlocks  = Just (map (fromMaybe 1) mbBlocks)
-            | otherwise             = Nothing
-        withNull f = f (InArray nullPtr)
-        withInList' = withInList . map hSize
-
-selectElements :: Dataspace -> SelectionOperator -> V.Vector (SV.Vector HSize) -> IO ()
-selectElements space@(Dataspace space_id) oper elems = do
-    nDims <- getSimpleDataspaceExtentNDims space
-
-    let nElems = V.length elems
-        packed = SV.generate (nElems * fromIntegral nDims) $ \i ->
-            case i `divMod` nElems of
-                (dim, elt) -> elems V.! elt SV.! dim
-
-    withErrorCheck_ $
-        withInVector packed $ \ielems ->
-            h5s_select_elements space_id (rawSelectionOperator oper) (fromIntegral nElems) (castWrappedPtr ielems)
-
--- TODO: determine whether to throw an exception or simply report it
--- when the returned value is invalid.
-getSimpleDataspaceExtentType :: Dataspace -> IO DataspaceClass
-getSimpleDataspaceExtentType (Dataspace space_id) =
-    fmap dataspaceClass $
-        withErrorWhen (\(H5S_class_t c) -> c < 0) $
-            h5s_get_simple_extent_type space_id
-
-setDataspaceExtentNone :: Dataspace -> IO ()
-setDataspaceExtentNone (Dataspace space_id) =
-    withErrorCheck_ $
-        h5s_set_extent_none space_id
-
-copyDataspaceExtent :: Dataspace -> Dataspace -> IO ()
-copyDataspaceExtent (Dataspace dst) (Dataspace src) =
-    withErrorCheck_ $
-        h5s_extent_copy dst src
-
-dataspaceExtentsEqual :: Dataspace -> Dataspace -> IO Bool
-dataspaceExtentsEqual (Dataspace s1) (Dataspace s2) =
-    htriToBool $
-        h5s_extent_equal s1 s2
-
-selectAll :: Dataspace -> IO ()
-selectAll (Dataspace space_id) =
-    withErrorCheck_ $
-        h5s_select_all space_id
-
-selectNone :: Dataspace -> IO ()
-selectNone (Dataspace space_id) =
-    withErrorCheck_ $
-        h5s_select_none space_id
-
-offsetSimpleDataspaceSelection :: Dataspace -> SV.Vector HSSize -> IO ()
-offsetSimpleDataspaceSelection space@(Dataspace space_id) offsets = do
-    nDims <- getSimpleDataspaceExtentNDims space
-
-    when (fromIntegral nDims /= SV.length offsets)
-        (fail "offsetSimpleDataspaceSelection: offset vector's length must equal number dimensions in dataspace")
-
-    withErrorCheck_ $
-        withInVector offsets $ \ioffsets ->
-            h5s_offset_simple space_id (castWrappedPtr ioffsets)
-
-selectionValid :: Dataspace -> IO Bool
-selectionValid (Dataspace space_id) =
-    htriToBool $
-        h5s_select_valid space_id
-
-getHyperslabSelection :: Dataspace -> IO (V.Vector (SV.Vector HSize, SV.Vector HSize))
-getHyperslabSelection space = getHyperslabSelectionBlockList space 0 maxBound
-
-getHyperslabSelectionNBlocks :: Dataspace -> IO HSize
-getHyperslabSelectionNBlocks (Dataspace space_id) =
-    fmap fromIntegral $
-        withErrorWhen (< 0) $
-            h5s_get_select_hyper_nblocks space_id
-
-getHyperslabSelectionBlockList :: Dataspace -> HSize -> HSize -> IO (V.Vector (SV.Vector HSize, SV.Vector HSize))
-getHyperslabSelectionBlockList space@(Dataspace space_id) startBlock numBlocks = do
-    n <- getHyperslabSelectionNBlocks space
-    nDims <- getSimpleDataspaceExtentNDims space
-
-    let nBlks = min numBlocks (n - startBlock)
-        blkSize = 2 * fromIntegral nDims
-        numSizes = nBlks * blkSize
-
-
-    sizes <- withOutVector_ (fromIntegral numSizes) $ \buf ->
-        withErrorCheck_ $
-            h5s_get_select_hyper_blocklist space_id (hSize startBlock) (hSize nBlks) (castWrappedPtr buf)
-
-    let decodePt i = SV.slice i (fromIntegral nDims) sizes
-        decodeBlock i = (decodePt b, decodePt (b + fromIntegral nDims))
-            where b = i * fromIntegral blkSize
-    return $! V.generate (fromIntegral nBlks) decodeBlock
-
-getElementSelection :: Dataspace -> IO (V.Vector (SV.Vector HSize))
-getElementSelection space = getElementSelectionPointList space 0 maxBound
-
-getElementSelectionNPoints :: Dataspace -> IO HSize
-getElementSelectionNPoints (Dataspace space_id) =
-    fmap fromIntegral $
-        withErrorWhen (< 0) $
-            h5s_get_select_elem_npoints space_id
-
-getElementSelectionPointList :: Dataspace -> HSize -> HSize -> IO (V.Vector (SV.Vector HSize))
-getElementSelectionPointList space@(Dataspace space_id) startPoint numPoints = do
-    n <- getElementSelectionNPoints space
-    nDims <- getSimpleDataspaceExtentNDims space
-
-    let nPts = min numPoints (n - startPoint)
-        sz = nPts * fromIntegral nDims
-
-    rawPoints <- withOutVector_ (fromIntegral sz) $ \buf ->
-        withErrorCheck_ $
-            h5s_get_select_elem_pointlist space_id (hSize startPoint) (hSize nPts) (castWrappedPtr buf)
-
-    let unpackPt i = SV.generate (fromIntegral nDims) $ \j -> rawPoints SV.! (i + j * fromIntegral nPts)
-
-    return $! V.generate (fromIntegral nPts) unpackPt
-
-getSelectionBounds :: Dataspace -> IO [(HSize, HSize)]
-getSelectionBounds space@(Dataspace space_id) = do
-    n <- getSimpleDataspaceExtentNDims space
-
-    (start, end) <-
-        withOutList (fromIntegral n) $ \start ->
-            withOutList_ (fromIntegral n) $ \end ->
-                withErrorCheck_ $
-                    h5s_get_select_bounds space_id start end
-
-    return [(HSize s, HSize e) | (s,e) <- zip start end]
-
-data SelectionType
-    = Points
-    | Hyperslabs
-    deriving (Eq, Ord, Bounded, Enum, Read, Show)
-
-selectionType :: H5S_sel_type -> Maybe SelectionType
-selectionType c
-    | c == h5s_SEL_NONE         = Nothing
-    | c == h5s_SEL_POINTS       = Just Points
-    | c == h5s_SEL_HYPERSLABS   = Just Hyperslabs
-    | otherwise                 = error ("unknown h5s_SEL value" ++ show c)
-
-getSelectionType :: Dataspace -> IO (Maybe SelectionType)
-getSelectionType (Dataspace space_id) =
-    fmap selectionType $
-        withErrorWhen (\(H5S_sel_type c) -> c < 0) $
-            h5s_get_select_type space_id
diff --git a/src/Bindings/HDF5/Dataspace.hsc b/src/Bindings/HDF5/Dataspace.hsc
new file mode 100644
--- /dev/null
+++ b/src/Bindings/HDF5/Dataspace.hsc
@@ -0,0 +1,375 @@
+#include <bindings.h>
+#include <H5version.h>
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE CPP #-}
+module Bindings.HDF5.Dataspace
+    ( Dataspace
+    , DataspaceClass(..)
+    , SelectionOperator(..)
+    , SelectionType(..)
+
+    , createDataspace
+    , createSimpleDataspace
+    , createExpandableDataspace
+
+    , copyDataspace
+
+    , closeDataspace
+
+    , encodeDataspace
+    , decodeDataspace
+
+    , getSimpleDataspaceExtentNPoints
+    , getSimpleDataspaceExtentNDims
+    , getSimpleDataspaceExtent
+
+    , isSimpleDataspace
+
+    , getDataspaceSelectionNPoints
+
+    , selectHyperslab
+    , selectElements
+
+    , getSimpleDataspaceExtentType
+
+    , setDataspaceExtentNone
+    , copyDataspaceExtent
+    , dataspaceExtentsEqual
+
+    , selectAll
+    , selectNone
+
+    , offsetSimpleDataspaceSelection
+
+    , selectionValid
+
+    , getHyperslabSelection
+    , getHyperslabSelectionNBlocks
+    , getHyperslabSelectionBlockList
+
+    , getElementSelection
+    , getElementSelectionNPoints
+    , getElementSelectionPointList
+
+    , getSelectionBounds
+
+    , getSelectionType
+    ) where
+
+import Bindings.HDF5.Core
+import Bindings.HDF5.Error
+import Bindings.HDF5.Object
+import Bindings.HDF5.Raw.H5I
+import Bindings.HDF5.Raw.H5S
+import Control.Exception (assert)
+import Control.Monad
+import qualified Data.ByteString as BS
+import qualified Data.ByteString.Unsafe as BS
+import Data.List
+import Data.Maybe
+import Data.Tagged
+import qualified Data.Vector as V
+import qualified Data.Vector.Storable as SV
+import Foreign(nullPtr)
+import Foreign.C
+import Foreign.Ptr.Conventions
+
+newtype Dataspace = Dataspace HId_t
+    deriving (Eq, HId, FromHId, HDFResultType)
+
+instance Object Dataspace where
+    staticObjectType = Tagged (Just DataspaceObj)
+
+data DataspaceClass
+    = Scalar
+    | Simple
+    | Null
+    deriving (Eq, Ord, Enum, Bounded, Read, Show)
+
+rawDataspaceClass :: DataspaceClass -> H5S_class_t
+rawDataspaceClass Scalar = h5s_SCALAR
+rawDataspaceClass Simple = h5s_SIMPLE
+rawDataspaceClass Null   = h5s_NULL
+
+dataspaceClass :: H5S_class_t -> DataspaceClass
+dataspaceClass c
+    | c == h5s_SCALAR   = Scalar
+    | c == h5s_SIMPLE   = Simple
+    | c == h5s_NULL     = Null
+    | otherwise         = error ("unknown dataspace class: " ++ show c)
+
+createDataspace :: DataspaceClass -> IO Dataspace
+createDataspace cls =
+    fmap Dataspace $
+        withErrorCheck $
+            h5s_create (rawDataspaceClass cls)
+
+createSimpleDataspace :: [HSize] -> IO Dataspace
+createSimpleDataspace dims =
+    fmap Dataspace $
+        withErrorCheck $
+            withInList (map hSize dims) $ \idims ->
+                h5s_create_simple n idims (InArray nullPtr)
+    where n = genericLength dims
+
+createExpandableDataspace :: [(HSize, Maybe HSize)] -> IO Dataspace
+createExpandableDataspace dims =
+    fmap Dataspace $
+        withErrorCheck $
+            withInList (map hSize dimSizes) $ \idimSizes ->
+                withInList (map (maybe h5s_UNLIMITED hSize) dimLimits) $ \idimLimits ->
+                    h5s_create_simple n idimSizes idimLimits
+    where
+        n = genericLength dims
+        (dimSizes, dimLimits) = unzip dims
+
+copyDataspace :: Dataspace -> IO Dataspace
+copyDataspace (Dataspace space_id) =
+    fmap Dataspace $
+        withErrorCheck $
+            h5s_copy space_id
+
+closeDataspace :: Dataspace -> IO ()
+closeDataspace (Dataspace space_id) =
+    withErrorCheck_ $
+        h5s_close space_id
+
+encodeDataspace :: Dataspace -> IO BS.ByteString
+encodeDataspace (Dataspace space_id) =
+    withOutByteString $ \buf bufSz ->
+        withInOut_ bufSz $ \ioBufSz ->
+            withErrorCheck_ $
+                h5s_encode space_id buf ioBufSz
+
+decodeDataspace :: BS.ByteString -> IO Dataspace
+decodeDataspace bs = BS.unsafeUseAsCString bs $ \buf ->
+    fmap Dataspace $
+        withErrorCheck $
+            h5s_decode (InArray buf)
+
+getSimpleDataspaceExtentNPoints :: Dataspace -> IO HSize
+getSimpleDataspaceExtentNPoints (Dataspace space_id) =
+    fmap fromIntegral $
+        withErrorWhen (< 0) $
+            h5s_get_simple_extent_npoints space_id
+
+getSimpleDataspaceExtentNDims :: Dataspace -> IO CInt
+getSimpleDataspaceExtentNDims (Dataspace space_id) =
+    withErrorWhen (< 0) $
+        h5s_get_simple_extent_ndims space_id
+
+getSimpleDataspaceExtent :: Dataspace -> IO ([HSize], [Maybe HSize])
+getSimpleDataspaceExtent space@(Dataspace space_id) = do
+    n <- getSimpleDataspaceExtentNDims space
+
+    (dims, (maxDims, n')) <-
+        withOutList (fromIntegral n) $ \dims ->
+            withOutList (fromIntegral n) $ \maxDims ->
+                withErrorWhen (< 0) $
+                    h5s_get_simple_extent_dims space_id dims maxDims
+
+    assert (n==n') $ return
+        ( map HSize dims
+        , [ if d == h5s_UNLIMITED then Nothing else Just (HSize d) | d <- maxDims]
+        )
+
+isSimpleDataspace :: Dataspace -> IO Bool
+isSimpleDataspace (Dataspace space_id) =
+    htriToBool $
+        h5s_is_simple space_id
+
+getDataspaceSelectionNPoints :: Dataspace -> IO HSize
+getDataspaceSelectionNPoints (Dataspace space_id) =
+    fmap fromIntegral $
+        withErrorWhen (< 0) $
+            h5s_get_select_npoints space_id
+
+data SelectionOperator
+    = Set
+    | Or
+    | And
+    | Xor
+    | NotB
+    | NotA
+    | Append
+    | Prepend
+    deriving (Eq, Ord, Enum, Bounded, Read, Show)
+
+rawSelectionOperator :: SelectionOperator -> H5S_seloper_t
+rawSelectionOperator Set     = h5s_SELECT_SET
+rawSelectionOperator Or      = h5s_SELECT_OR
+rawSelectionOperator And     = h5s_SELECT_AND
+rawSelectionOperator Xor     = h5s_SELECT_XOR
+rawSelectionOperator NotB    = h5s_SELECT_NOTB
+rawSelectionOperator NotA    = h5s_SELECT_NOTA
+rawSelectionOperator Append  = h5s_SELECT_APPEND
+rawSelectionOperator Prepend = h5s_SELECT_PREPEND
+
+selectHyperslab :: Dataspace -> SelectionOperator -> [(HSize, Maybe HSize, HSize, Maybe HSize)] -> IO ()
+selectHyperslab space@(Dataspace space_id) oper hyperSlab = do
+    nDims <- getSimpleDataspaceExtentNDims space
+
+    when (length hyperSlab /= fromIntegral nDims)
+        (fail "selectHyperslab: the given hyperslab has the wrong number of dimensions for this dataspace")
+
+    withErrorCheck_ $
+        withInList' start $ \istart ->
+            maybe withNull withInList' stride $ \istride ->
+                withInList' count $ \icount ->
+                    maybe withNull withInList' block $ \iblock ->
+                        h5s_select_hyperslab space_id (rawSelectionOperator oper) istart istride icount iblock
+    where
+        (start, mbStrides, count, mbBlocks) = unzip4 hyperSlab
+        stride
+            | any isJust mbStrides  = Just (map (fromMaybe 1) mbStrides)
+            | otherwise             = Nothing
+        block
+            | any isJust mbBlocks  = Just (map (fromMaybe 1) mbBlocks)
+            | otherwise             = Nothing
+        withNull f = f (InArray nullPtr)
+        withInList' = withInList . map hSize
+
+selectElements :: Dataspace -> SelectionOperator -> V.Vector (SV.Vector HSize) -> IO ()
+selectElements space@(Dataspace space_id) oper elems = do
+    nDims <- getSimpleDataspaceExtentNDims space
+
+    let nElems = V.length elems
+        packed = SV.generate (nElems * fromIntegral nDims) $ \i ->
+            case i `divMod` nElems of
+                (dim, elt) -> elems V.! elt SV.! dim
+
+    withErrorCheck_ $
+        withInVector packed $ \ielems ->
+            h5s_select_elements space_id (rawSelectionOperator oper) (fromIntegral nElems) (castWrappedPtr ielems)
+
+-- TODO: determine whether to throw an exception or simply report it
+-- when the returned value is invalid.
+getSimpleDataspaceExtentType :: Dataspace -> IO DataspaceClass
+getSimpleDataspaceExtentType (Dataspace space_id) =
+    fmap dataspaceClass $
+        withErrorWhen (\(H5S_class_t c) -> c < 0) $
+            h5s_get_simple_extent_type space_id
+
+setDataspaceExtentNone :: Dataspace -> IO ()
+setDataspaceExtentNone (Dataspace space_id) =
+    withErrorCheck_ $
+        h5s_set_extent_none space_id
+
+copyDataspaceExtent :: Dataspace -> Dataspace -> IO ()
+copyDataspaceExtent (Dataspace dst) (Dataspace src) =
+    withErrorCheck_ $
+        h5s_extent_copy dst src
+
+dataspaceExtentsEqual :: Dataspace -> Dataspace -> IO Bool
+dataspaceExtentsEqual (Dataspace s1) (Dataspace s2) =
+    htriToBool $
+        h5s_extent_equal s1 s2
+
+selectAll :: Dataspace -> IO ()
+selectAll (Dataspace space_id) =
+    withErrorCheck_ $
+        h5s_select_all space_id
+
+selectNone :: Dataspace -> IO ()
+selectNone (Dataspace space_id) =
+    withErrorCheck_ $
+        h5s_select_none space_id
+
+offsetSimpleDataspaceSelection :: Dataspace -> SV.Vector HSSize -> IO ()
+offsetSimpleDataspaceSelection space@(Dataspace space_id) offsets = do
+    nDims <- getSimpleDataspaceExtentNDims space
+
+    when (fromIntegral nDims /= SV.length offsets)
+        (fail "offsetSimpleDataspaceSelection: offset vector's length must equal number dimensions in dataspace")
+
+    withErrorCheck_ $
+        withInVector offsets $ \ioffsets ->
+            h5s_offset_simple space_id (castWrappedPtr ioffsets)
+
+selectionValid :: Dataspace -> IO Bool
+selectionValid (Dataspace space_id) =
+    htriToBool $
+        h5s_select_valid space_id
+
+getHyperslabSelection :: Dataspace -> IO (V.Vector (SV.Vector HSize, SV.Vector HSize))
+getHyperslabSelection space = getHyperslabSelectionBlockList space 0 maxBound
+
+getHyperslabSelectionNBlocks :: Dataspace -> IO HSize
+getHyperslabSelectionNBlocks (Dataspace space_id) =
+    fmap fromIntegral $
+        withErrorWhen (< 0) $
+            h5s_get_select_hyper_nblocks space_id
+
+getHyperslabSelectionBlockList :: Dataspace -> HSize -> HSize -> IO (V.Vector (SV.Vector HSize, SV.Vector HSize))
+getHyperslabSelectionBlockList space@(Dataspace space_id) startBlock numBlocks = do
+    n <- getHyperslabSelectionNBlocks space
+    nDims <- getSimpleDataspaceExtentNDims space
+
+    let nBlks = min numBlocks (n - startBlock)
+        blkSize = 2 * fromIntegral nDims
+        numSizes = nBlks * blkSize
+
+
+    sizes <- withOutVector_ (fromIntegral numSizes) $ \buf ->
+        withErrorCheck_ $
+            h5s_get_select_hyper_blocklist space_id (hSize startBlock) (hSize nBlks) (castWrappedPtr buf)
+
+    let decodePt i = SV.slice i (fromIntegral nDims) sizes
+        decodeBlock i = (decodePt b, decodePt (b + fromIntegral nDims))
+            where b = i * fromIntegral blkSize
+    return $! V.generate (fromIntegral nBlks) decodeBlock
+
+getElementSelection :: Dataspace -> IO (V.Vector (SV.Vector HSize))
+getElementSelection space = getElementSelectionPointList space 0 maxBound
+
+getElementSelectionNPoints :: Dataspace -> IO HSize
+getElementSelectionNPoints (Dataspace space_id) =
+    fmap fromIntegral $
+        withErrorWhen (< 0) $
+            h5s_get_select_elem_npoints space_id
+
+getElementSelectionPointList :: Dataspace -> HSize -> HSize -> IO (V.Vector (SV.Vector HSize))
+getElementSelectionPointList space@(Dataspace space_id) startPoint numPoints = do
+    n <- getElementSelectionNPoints space
+    nDims <- getSimpleDataspaceExtentNDims space
+
+    let nPts = min numPoints (n - startPoint)
+        sz = nPts * fromIntegral nDims
+
+    rawPoints <- withOutVector_ (fromIntegral sz) $ \buf ->
+        withErrorCheck_ $
+            h5s_get_select_elem_pointlist space_id (hSize startPoint) (hSize nPts) (castWrappedPtr buf)
+
+    let unpackPt i = SV.generate (fromIntegral nDims) $ \j -> rawPoints SV.! (i + j * fromIntegral nPts)
+
+    return $! V.generate (fromIntegral nPts) unpackPt
+
+getSelectionBounds :: Dataspace -> IO [(HSize, HSize)]
+getSelectionBounds space@(Dataspace space_id) = do
+    n <- getSimpleDataspaceExtentNDims space
+
+    (start, end) <-
+        withOutList (fromIntegral n) $ \start ->
+            withOutList_ (fromIntegral n) $ \end ->
+                withErrorCheck_ $
+                    h5s_get_select_bounds space_id start end
+
+    return [(HSize s, HSize e) | (s,e) <- zip start end]
+
+data SelectionType
+    = Points
+    | Hyperslabs
+    deriving (Eq, Ord, Bounded, Enum, Read, Show)
+
+selectionType :: H5S_sel_type -> Maybe SelectionType
+selectionType c
+    | c == h5s_SEL_NONE         = Nothing
+    | c == h5s_SEL_POINTS       = Just Points
+    | c == h5s_SEL_HYPERSLABS   = Just Hyperslabs
+    | otherwise                 = error ("unknown h5s_SEL value" ++ show c)
+
+getSelectionType :: Dataspace -> IO (Maybe SelectionType)
+getSelectionType (Dataspace space_id) =
+    fmap selectionType $
+        withErrorWhen (\(H5S_sel_type c) -> c < 0) $
+            h5s_get_select_type space_id
diff --git a/src/Bindings/HDF5/ErrorCodes.hs b/src/Bindings/HDF5/ErrorCodes.hs
deleted file mode 100644
--- a/src/Bindings/HDF5/ErrorCodes.hs
+++ /dev/null
@@ -1,500 +0,0 @@
-{-# LANGUAGE DeriveDataTypeable, FlexibleInstances #-}
-module Bindings.HDF5.ErrorCodes
-    ( MajorErrCode(..), majorErrorCode, majorErrorFromCode
-    , MinorErrCode(..), minorErrorCode, minorErrorFromCode
-
-    ) where
-import Data.Maybe
-
-import Bindings.HDF5.Raw.H5E
-import Bindings.HDF5.Raw.H5I
-import Data.Typeable (Typeable)
-import Foreign
-
-data MajorErrCode
-    -- |Dataset
-    = Dataset
-    -- |Function entry/exit
-    | Func
-    -- |Data storage
-    | Storage
-    -- |File accessability
-    | File
-    -- |Shared Object Header Messages
-    | SOHM
-    -- |Symbol table
-    | Sym
-    -- |Virtual File Layer
-    | VFL
-    -- |Internal error (too specific to document in detail)
-    | Internal
-    -- |B-Tree node
-    | BTree
-    -- |References
-    | Reference
-    -- |Dataspace
-    | Dataspace
-    -- |Resource unavailable
-    | Resource
-    -- |Property lists
-    | PList
-    -- |Links
-    | Link
-    -- |Datatype
-    | Datatype
-    -- |Reference Counted Strings
-    | RS
-    -- |Heap
-    | Heap
-    -- |Object header
-    | OHDR
-    -- |Object atom
-    | Atom
-    -- |Attribute
-    | Attr
-    -- |Low-level I/O
-    | IO
-    -- |Skip Lists
-    | SList
-    -- |External file list
-    | EFL
-    -- |Ternary Search Trees
-    | TST
-    -- |Invalid arguments to routine
-    | Args
-    -- |Error API
-    | Error
-    -- |Data filters
-    | PLine
-    -- |Free Space Manager
-    | FSpace
-    -- |Object cache
-    | Cache
-
-    -- |Unrecognized major error code
-    | UnknownMajor HId_t
-    deriving (Eq, Ord, Show, Typeable)
-
-rawMajorErrCodesInv :: [(HId_t, Maybe MajorErrCode)]
-rawMajorErrCodesInv = [(a,b) | (b,a) <- rawMajorErrCodes]
-
-rawMajorErrCodes :: [(Maybe MajorErrCode, HId_t)]
-rawMajorErrCodes =
-    [ (Nothing,         h5e_NONE_MAJOR)
-    , (Just Dataset,    h5e_DATASET)
-    , (Just Func,       h5e_FUNC)
-    , (Just Storage,    h5e_STORAGE)
-    , (Just File,       h5e_FILE)
-    , (Just SOHM,       h5e_SOHM)
-    , (Just Sym,        h5e_SYM)
-    , (Just VFL,        h5e_VFL)
-    , (Just Internal,   h5e_INTERNAL)
-    , (Just BTree,      h5e_BTREE)
-    , (Just Reference,  h5e_REFERENCE)
-    , (Just Dataspace,  h5e_DATASPACE)
-    , (Just Resource,   h5e_RESOURCE)
-    , (Just PList,      h5e_PLIST)
-    , (Just Link,       h5e_LINK)
-    , (Just Datatype,   h5e_DATATYPE)
-    , (Just RS,         h5e_RS)
-    , (Just Heap,       h5e_HEAP)
-    , (Just OHDR,       h5e_OHDR)
-    , (Just Atom,       h5e_ATOM)
-    , (Just Attr,       h5e_ATTR)
-    , (Just IO,         h5e_IO)
-    , (Just SList,      h5e_SLIST)
-    , (Just EFL,        h5e_EFL)
-    , (Just TST,        h5e_TST)
-    , (Just Args,       h5e_ARGS)
-    , (Just Error,      h5e_ERROR)
-    , (Just PLine,      h5e_PLINE)
-    , (Just FSpace,     h5e_FSPACE)
-    , (Just Cache,      h5e_CACHE)
-    ]
-
-majorErrorCode :: Maybe MajorErrCode -> Maybe HId_t
-majorErrorCode (Just (UnknownMajor code)) = Just code
-majorErrorCode err = lookup err rawMajorErrCodes
-
-majorErrorFromCode :: HId_t -> Maybe MajorErrCode
-majorErrorFromCode code =
-    fromMaybe (Just (UnknownMajor code))
-                  (lookup code rawMajorErrCodesInv)
-
-instance Storable (Maybe MajorErrCode) where
-    sizeOf    _ = sizeOf    (undefined :: HId_t)
-    alignment _ = alignment (undefined :: HId_t)
-
-    peek = fmap majorErrorFromCode . peek . castPtr
-    poke p err = case majorErrorCode err of
-        Nothing -> fail ("Unknown major error code: " ++ show err)
-        Just code -> poke (castPtr p) code
-
-data MinorErrCode
-    = SeekError
-    -- |Read failed
-    | ReadError
-    -- |Write failed
-    | WriteError
-    -- |Close failed
-    | CloseError
-    -- |Address overflowed
-    | Overflow
-    -- |File control (fcntl) failed
-    | FCNTL
-    -- |No space available for allocation
-    | NoSpace
-    -- |Can't allocate space
-    | CantAlloc
-    -- |Unable to copy object
-    | CantCopy
-    -- |Unable to free object
-    | CantFree
-    -- |Object already exists
-    | AlreadyExists
-    -- |Unable to lock object
-    | CantLock
-    -- |Unable to unlock object
-    | CantUnlock
-    -- |Unable to garbage collect
-    | CantGC
-    -- |Unable to compute size
-    | CantGetSize
-    -- |Object is already open
-    | ObjOpen
-    -- |Can't restore condition
-    | CantRestore
-    -- |Can't compute value
-    | CantCompute
-    -- |Can't extend heap's space
-    | CantExtend
-    -- |Can't attach object
-    | CantAttach
-    -- |Can't update object
-    | CantUpdate
-    -- |Can't operate on object
-    | CantOperate
-    -- |Unable to initialize object
-    | CantInit
-    -- |Object already initialized
-    | AlreadyInit
-    -- |Unable to release object
-    | CantRelease
-    -- |Can't get value
-    | CantGet
-    -- |Can't set value
-    | CantSet
-    -- |Duplicate class name in parent class
-    | DupClass
-    -- |Can't merge objects
-    | CantMerge
-    -- |Can't revive object
-    | CantRevive
-    -- |Can't shrink container
-    | CantShrink
-    -- |Bad object header link count
-    | LinkCount
-    -- |Wrong version number
-    | Version
-    -- |Alignment error
-    | Alignment
-    -- |Unrecognized message
-    | BadMesg
-    -- |Can't delete message
-    | CantDelete
-    -- |Iteration failed
-    | BadIter
-    -- |Can't pack messages
-    | CantPack
-    -- |Can't reset object
-    | CantReset
-    -- |Unable to rename object
-    | CantRename
-    -- |System error message
-    | SysErrStr
-    -- |Requested filter is not available
-    | NoFilter
-    -- |Callback failed
-    | Callback
-    -- |Error from filter 'can apply' callback
-    | CanApply
-    -- |Error from filter 'set local' callback
-    | SetLocal
-    -- |Filter present but encoding disabled
-    | NoEncoder
-    -- |Filter operation failed
-    | CantFilter
-    -- |Can't open object
-    | CantOpenObj
-    -- |Can't close object
-    | CantCloseObj
-    -- |Name component is too long
-    | CompLen
-    -- |Problem with path to object
-    | Path
-    -- |File already exists
-    | FileExists
-    -- |File already open
-    | FileOpen
-    -- |Unable to create file
-    | CantCreate
-    -- |Unable to open file
-    | CantOpenFile
-    -- |Unable to close file
-    | CantCloseFile
-    -- |Not an HDF5 file
-    | NotHDF5
-    -- |Bad file ID accessed
-    | BadFile
-    -- |File has been truncated
-    | Truncated
-    -- |File mount error
-    | Mount
-    -- |Unable to find atom information (already closed?)
-    | BadAtom
-    -- |Unable to find ID group information
-    | BadGroup
-    -- |Unable to register new atom
-    | CantRegister
-    -- |Unable to increment reference count
-    | CantInc
-    -- |Unable to decrement reference count
-    | CantDec
-    -- |Out of IDs for group
-    | NoIds
-    -- |Unable to flush data from cache
-    | CantFlush
-    -- |Unable to serialize data from cache
-    | CantSerialize
-    -- |Unable to load metadata into cache
-    | CantLoad
-    -- |Protected metadata error
-    | Protect
-    -- |Metadata not currently cached
-    | NotCached
-    -- |Internal error detected
-    | System
-    -- |Unable to insert metadata into cache
-    | CantIns
-    -- |Unable to protect metadata
-    | CantProtect
-    -- |Unable to unprotect metadata
-    | CanTUnprotect
-    -- |Unable to pin cache entry
-    | CantPin
-    -- |Unable to un-pin cache entry
-    | CantUnpin
-    -- |Unable to mark a pinned entry as dirty
-    | CantMarkDirty
-    -- |Unable to mark metadata as dirty
-    | CantDirty
-    -- |Unable to expunge a metadata cache entry
-    | CantExpunge
-    -- |Unable to resize a metadata cache entry
-    | CantResize
-    -- |Link traversal failure
-    | Traverse
-    -- |Too many soft links in path
-    | NLinks
-    -- |Link class not registered
-    | NotRegistered
-    -- |Can't move object
-    | CantMove
-    -- |Can't sort objects
-    | CantSort
-    -- |Some MPI function failed
-    | MPI
-    -- |MPI Error String
-    | MPIErrStr
-    -- |Can't receive data
-    | CantRecv
-    -- |Can't clip hyperslab region
-    | CantClip
-    -- |Can't count elements
-    | CantCount
-    -- |Can't select hyperslab
-    | CantSelect
-    -- |Can't move to next iterator location
-    | CantNext
-    -- |Invalid selection
-    | BadSelect
-    -- |Can't compare objects
-    | CantCompare
-    -- |Information is uinitialized
-    | Uninitialized
-    -- |Feature is unsupported
-    | Unsupported
-    -- |Inappropriate type
-    | BadType
-    -- |Out of range
-    | BadRange
-    -- |Bad value
-    | BadValue
-    -- |Object not found
-    | NotFound
-    -- |Object already exists
-    | Exists
-    -- |Unable to encode value
-    | CantEncode
-    -- |Unable to decode value
-    | CantDecode
-    -- |Unable to split node
-    | CantSplit
-    -- |Unable to redistribute records
-    | CantRedistribute
-    -- |Unable to swap records
-    | CantSwap
-    -- |Unable to insert object
-    | CantInsert
-    -- |Unable to list node
-    | CantList
-    -- |Unable to modify record
-    | CantModify
-    -- |Unable to remove object
-    | CantRemove
-    -- |Can't convert datatypes
-    | CantConvert
-    -- |Bad size for object
-    | BadSize
-
-    -- |Unrecognized minor error code
-    | UnknownMinor HId_t
-    deriving (Eq, Ord, Show, Typeable)
-
-rawMinorErrCodesInv :: [(HId_t, Maybe MinorErrCode)]
-rawMinorErrCodesInv = [(a,b) | (b,a) <- rawMinorErrCodes]
-rawMinorErrCodes :: [(Maybe MinorErrCode, HId_t)]
-rawMinorErrCodes =
-    [ (Nothing,                 h5e_NONE_MINOR)
-    , (Just SeekError,          h5e_SEEKERROR)
-    , (Just ReadError,          h5e_READERROR)
-    , (Just WriteError,         h5e_WRITEERROR)
-    , (Just CloseError,         h5e_CLOSEERROR)
-    , (Just Overflow,           h5e_OVERFLOW)
-    , (Just FCNTL,              h5e_FCNTL)
-    , (Just NoSpace,            h5e_NOSPACE)
-    , (Just CantAlloc,          h5e_CANTALLOC)
-    , (Just CantCopy,           h5e_CANTCOPY)
-    , (Just CantFree,           h5e_CANTFREE)
-    , (Just AlreadyExists,      h5e_ALREADYEXISTS)
-    , (Just CantLock,           h5e_CANTLOCK)
-    , (Just CantUnlock,         h5e_CANTUNLOCK)
-    , (Just CantGC,             h5e_CANTGC)
-    , (Just CantGetSize,        h5e_CANTGETSIZE)
-    , (Just ObjOpen,            h5e_OBJOPEN)
-    , (Just CantRestore,        h5e_CANTRESTORE)
-    , (Just CantCompute,        h5e_CANTCOMPUTE)
-    , (Just CantExtend,         h5e_CANTEXTEND)
-    , (Just CantAttach,         h5e_CANTATTACH)
-    , (Just CantUpdate,         h5e_CANTUPDATE)
-    , (Just CantOperate,        h5e_CANTOPERATE)
-    , (Just CantInit,           h5e_CANTINIT)
-    , (Just AlreadyInit,        h5e_ALREADYINIT)
-    , (Just CantRelease,        h5e_CANTRELEASE)
-    , (Just CantGet,            h5e_CANTGET)
-    , (Just CantSet,            h5e_CANTSET)
-    , (Just DupClass,           h5e_DUPCLASS)
-    , (Just CantMerge,          h5e_CANTMERGE)
-    , (Just CantRevive,         h5e_CANTREVIVE)
-    , (Just CantShrink,         h5e_CANTSHRINK)
-    , (Just LinkCount,          h5e_LINKCOUNT)
-    , (Just Version,            h5e_VERSION)
-    , (Just Alignment,          h5e_ALIGNMENT)
-    , (Just BadMesg,            h5e_BADMESG)
-    , (Just CantDelete,         h5e_CANTDELETE)
-    , (Just BadIter,            h5e_BADITER)
-    , (Just CantPack,           h5e_CANTPACK)
-    , (Just CantReset,          h5e_CANTRESET)
-    , (Just CantRename,         h5e_CANTRENAME)
-    , (Just SysErrStr,          h5e_SYSERRSTR)
-    , (Just NoFilter,           h5e_NOFILTER)
-    , (Just Callback,           h5e_CALLBACK)
-    , (Just CanApply,           h5e_CANAPPLY)
-    , (Just SetLocal,           h5e_SETLOCAL)
-    , (Just NoEncoder,          h5e_NOENCODER)
-    , (Just CantFilter,         h5e_CANTFILTER)
-    , (Just CantOpenObj,        h5e_CANTOPENOBJ)
-    , (Just CantCloseObj,       h5e_CANTCLOSEOBJ)
-    , (Just CompLen,            h5e_COMPLEN)
-    , (Just Path,               h5e_PATH)
-    , (Just FileExists,         h5e_FILEEXISTS)
-    , (Just FileOpen,           h5e_FILEOPEN)
-    , (Just CantCreate,         h5e_CANTCREATE)
-    , (Just CantOpenFile,       h5e_CANTOPENFILE)
-    , (Just CantCloseFile,      h5e_CANTCLOSEFILE)
-    , (Just NotHDF5,            h5e_NOTHDF5)
-    , (Just BadFile,            h5e_BADFILE)
-    , (Just Truncated,          h5e_TRUNCATED)
-    , (Just Mount,              h5e_MOUNT)
-    , (Just BadAtom,            h5e_BADATOM)
-    , (Just BadGroup,           h5e_BADGROUP)
-    , (Just CantRegister,       h5e_CANTREGISTER)
-    , (Just CantInc,            h5e_CANTINC)
-    , (Just CantDec,            h5e_CANTDEC)
-    , (Just NoIds,              h5e_NOIDS)
-    , (Just CantFlush,          h5e_CANTFLUSH)
-    , (Just CantSerialize,      h5e_CANTSERIALIZE)
-    , (Just CantLoad,           h5e_CANTLOAD)
-    , (Just Protect,            h5e_PROTECT)
-    , (Just NotCached,          h5e_NOTCACHED)
-    , (Just System,             h5e_SYSTEM)
-    , (Just CantIns,            h5e_CANTINS)
-    , (Just CantProtect,        h5e_CANTPROTECT)
-    , (Just CanTUnprotect,      h5e_CANTUNPROTECT)
-    , (Just CantPin,            h5e_CANTPIN)
-    , (Just CantUnpin,          h5e_CANTUNPIN)
-    , (Just CantMarkDirty,      h5e_CANTMARKDIRTY)
-    , (Just CantDirty,          h5e_CANTDIRTY)
-    , (Just CantExpunge,        h5e_CANTEXPUNGE)
-    , (Just CantResize,         h5e_CANTRESIZE)
-    , (Just Traverse,           h5e_TRAVERSE)
-    , (Just NLinks,             h5e_NLINKS)
-    , (Just NotRegistered,      h5e_NOTREGISTERED)
-    , (Just CantMove,           h5e_CANTMOVE)
-    , (Just CantSort,           h5e_CANTSORT)
-    , (Just MPI,                h5e_MPI)
-    , (Just MPIErrStr,          h5e_MPIERRSTR)
-    , (Just CantRecv,           h5e_CANTRECV)
-    , (Just CantClip,           h5e_CANTCLIP)
-    , (Just CantCount,          h5e_CANTCOUNT)
-    , (Just CantSelect,         h5e_CANTSELECT)
-    , (Just CantNext,           h5e_CANTNEXT)
-    , (Just BadSelect,          h5e_BADSELECT)
-    , (Just CantCompare,        h5e_CANTCOMPARE)
-    , (Just Uninitialized,      h5e_UNINITIALIZED)
-    , (Just Unsupported,        h5e_UNSUPPORTED)
-    , (Just BadType,            h5e_BADTYPE)
-    , (Just BadRange,           h5e_BADRANGE)
-    , (Just BadValue,           h5e_BADVALUE)
-    , (Just NotFound,           h5e_NOTFOUND)
-    , (Just Exists,             h5e_EXISTS)
-    , (Just CantEncode,         h5e_CANTENCODE)
-    , (Just CantDecode,         h5e_CANTDECODE)
-    , (Just CantSplit,          h5e_CANTSPLIT)
-    , (Just CantRedistribute,   h5e_CANTREDISTRIBUTE)
-    , (Just CantSwap,           h5e_CANTSWAP)
-    , (Just CantInsert,         h5e_CANTINSERT)
-    , (Just CantList,           h5e_CANTLIST)
-    , (Just CantModify,         h5e_CANTMODIFY)
-    , (Just CantRemove,         h5e_CANTREMOVE)
-    , (Just CantConvert,        h5e_CANTCONVERT)
-    , (Just BadSize,            h5e_BADSIZE)
-    ]
-
-minorErrorCode :: Maybe MinorErrCode -> Maybe HId_t
-minorErrorCode (Just (UnknownMinor code)) = Just code
-minorErrorCode err = lookup err rawMinorErrCodes
-
-minorErrorFromCode :: HId_t -> Maybe MinorErrCode
-minorErrorFromCode code =
-    fromMaybe (Just (UnknownMinor code))
-                  (lookup code rawMinorErrCodesInv)
-
-instance Storable (Maybe MinorErrCode) where
-    sizeOf    _ = sizeOf    (undefined :: HId_t)
-    alignment _ = alignment (undefined :: HId_t)
-
-    peek = fmap minorErrorFromCode . peek . castPtr
-    poke p err = case minorErrorCode err of
-        Nothing -> fail ("Unknown minor error code: " ++ show err)
-        Just code -> poke (castPtr p) code
diff --git a/src/Bindings/HDF5/ErrorCodes.hsc b/src/Bindings/HDF5/ErrorCodes.hsc
new file mode 100644
--- /dev/null
+++ b/src/Bindings/HDF5/ErrorCodes.hsc
@@ -0,0 +1,508 @@
+#include <bindings.h>
+#include <H5version.h>
+
+{-# LANGUAGE DeriveDataTypeable, FlexibleInstances #-}
+{-# LANGUAGE CPP #-}
+module Bindings.HDF5.ErrorCodes
+    ( MajorErrCode(..), majorErrorCode, majorErrorFromCode
+    , MinorErrCode(..), minorErrorCode, minorErrorFromCode
+
+    ) where
+import Data.Maybe
+
+import Bindings.HDF5.Raw.H5E
+import Bindings.HDF5.Raw.H5I
+import Data.Typeable (Typeable)
+import Foreign
+
+data MajorErrCode
+    -- |Dataset
+    = Dataset
+    -- |Function entry/exit
+    | Func
+    -- |Data storage
+    | Storage
+    -- |File accessability
+    | File
+    -- |Shared Object Header Messages
+    | SOHM
+    -- |Symbol table
+    | Sym
+    -- |Virtual File Layer
+    | VFL
+    -- |Internal error (too specific to document in detail)
+    | Internal
+    -- |B-Tree node
+    | BTree
+    -- |References
+    | Reference
+    -- |Dataspace
+    | Dataspace
+    -- |Resource unavailable
+    | Resource
+    -- |Property lists
+    | PList
+    -- |Links
+    | Link
+    -- |Datatype
+    | Datatype
+    -- |Reference Counted Strings
+    | RS
+    -- |Heap
+    | Heap
+    -- |Object header
+    | OHDR
+    -- |Object atom
+    | Atom
+    -- |Attribute
+    | Attr
+    -- |Low-level I/O
+    | IO
+    -- |Skip Lists
+    | SList
+    -- |External file list
+    | EFL
+    -- |Ternary Search Trees
+    | TST
+    -- |Invalid arguments to routine
+    | Args
+    -- |Error API
+    | Error
+    -- |Data filters
+    | PLine
+    -- |Free Space Manager
+    | FSpace
+    -- |Object cache
+    | Cache
+
+    -- |Unrecognized major error code
+    | UnknownMajor HId_t
+    deriving (Eq, Ord, Show, Typeable)
+
+rawMajorErrCodesInv :: [(HId_t, Maybe MajorErrCode)]
+rawMajorErrCodesInv = [(a,b) | (b,a) <- rawMajorErrCodes]
+
+rawMajorErrCodes :: [(Maybe MajorErrCode, HId_t)]
+rawMajorErrCodes =
+    [ (Nothing,         h5e_NONE_MAJOR)
+    , (Just Dataset,    h5e_DATASET)
+    , (Just Func,       h5e_FUNC)
+    , (Just Storage,    h5e_STORAGE)
+    , (Just File,       h5e_FILE)
+    , (Just SOHM,       h5e_SOHM)
+    , (Just Sym,        h5e_SYM)
+    , (Just VFL,        h5e_VFL)
+    , (Just Internal,   h5e_INTERNAL)
+    , (Just BTree,      h5e_BTREE)
+    , (Just Reference,  h5e_REFERENCE)
+    , (Just Dataspace,  h5e_DATASPACE)
+    , (Just Resource,   h5e_RESOURCE)
+    , (Just PList,      h5e_PLIST)
+    , (Just Link,       h5e_LINK)
+    , (Just Datatype,   h5e_DATATYPE)
+    , (Just RS,         h5e_RS)
+    , (Just Heap,       h5e_HEAP)
+    , (Just OHDR,       h5e_OHDR)
+#if !H5_VERSION_GE(1,8,14)
+    , (Just Atom,       h5e_ATOM)
+#endif
+    , (Just Attr,       h5e_ATTR)
+    , (Just IO,         h5e_IO)
+    , (Just SList,      h5e_SLIST)
+    , (Just EFL,        h5e_EFL)
+    , (Just TST,        h5e_TST)
+    , (Just Args,       h5e_ARGS)
+    , (Just Error,      h5e_ERROR)
+    , (Just PLine,      h5e_PLINE)
+    , (Just FSpace,     h5e_FSPACE)
+    , (Just Cache,      h5e_CACHE)
+    ]
+
+majorErrorCode :: Maybe MajorErrCode -> Maybe HId_t
+majorErrorCode (Just (UnknownMajor code)) = Just code
+majorErrorCode err = lookup err rawMajorErrCodes
+
+majorErrorFromCode :: HId_t -> Maybe MajorErrCode
+majorErrorFromCode code =
+    fromMaybe (Just (UnknownMajor code))
+                  (lookup code rawMajorErrCodesInv)
+
+instance Storable (Maybe MajorErrCode) where
+    sizeOf    _ = sizeOf    (undefined :: HId_t)
+    alignment _ = alignment (undefined :: HId_t)
+
+    peek = fmap majorErrorFromCode . peek . castPtr
+    poke p err = case majorErrorCode err of
+        Nothing -> fail ("Unknown major error code: " ++ show err)
+        Just code -> poke (castPtr p) code
+
+data MinorErrCode
+    = SeekError
+    -- |Read failed
+    | ReadError
+    -- |Write failed
+    | WriteError
+    -- |Close failed
+    | CloseError
+    -- |Address overflowed
+    | Overflow
+    -- |File control (fcntl) failed
+    | FCNTL
+    -- |No space available for allocation
+    | NoSpace
+    -- |Can't allocate space
+    | CantAlloc
+    -- |Unable to copy object
+    | CantCopy
+    -- |Unable to free object
+    | CantFree
+    -- |Object already exists
+    | AlreadyExists
+    -- |Unable to lock object
+    | CantLock
+    -- |Unable to unlock object
+    | CantUnlock
+    -- |Unable to garbage collect
+    | CantGC
+    -- |Unable to compute size
+    | CantGetSize
+    -- |Object is already open
+    | ObjOpen
+    -- |Can't restore condition
+    | CantRestore
+    -- |Can't compute value
+    | CantCompute
+    -- |Can't extend heap's space
+    | CantExtend
+    -- |Can't attach object
+    | CantAttach
+    -- |Can't update object
+    | CantUpdate
+    -- |Can't operate on object
+    | CantOperate
+    -- |Unable to initialize object
+    | CantInit
+    -- |Object already initialized
+    | AlreadyInit
+    -- |Unable to release object
+    | CantRelease
+    -- |Can't get value
+    | CantGet
+    -- |Can't set value
+    | CantSet
+    -- |Duplicate class name in parent class
+    | DupClass
+    -- |Can't merge objects
+    | CantMerge
+    -- |Can't revive object
+    | CantRevive
+    -- |Can't shrink container
+    | CantShrink
+    -- |Bad object header link count
+    | LinkCount
+    -- |Wrong version number
+    | Version
+    -- |Alignment error
+    | Alignment
+    -- |Unrecognized message
+    | BadMesg
+    -- |Can't delete message
+    | CantDelete
+    -- |Iteration failed
+    | BadIter
+    -- |Can't pack messages
+    | CantPack
+    -- |Can't reset object
+    | CantReset
+    -- |Unable to rename object
+    | CantRename
+    -- |System error message
+    | SysErrStr
+    -- |Requested filter is not available
+    | NoFilter
+    -- |Callback failed
+    | Callback
+    -- |Error from filter 'can apply' callback
+    | CanApply
+    -- |Error from filter 'set local' callback
+    | SetLocal
+    -- |Filter present but encoding disabled
+    | NoEncoder
+    -- |Filter operation failed
+    | CantFilter
+    -- |Can't open object
+    | CantOpenObj
+    -- |Can't close object
+    | CantCloseObj
+    -- |Name component is too long
+    | CompLen
+    -- |Problem with path to object
+    | Path
+    -- |File already exists
+    | FileExists
+    -- |File already open
+    | FileOpen
+    -- |Unable to create file
+    | CantCreate
+    -- |Unable to open file
+    | CantOpenFile
+    -- |Unable to close file
+    | CantCloseFile
+    -- |Not an HDF5 file
+    | NotHDF5
+    -- |Bad file ID accessed
+    | BadFile
+    -- |File has been truncated
+    | Truncated
+    -- |File mount error
+    | Mount
+    -- |Unable to find atom information (already closed?)
+    | BadAtom
+    -- |Unable to find ID group information
+    | BadGroup
+    -- |Unable to register new atom
+    | CantRegister
+    -- |Unable to increment reference count
+    | CantInc
+    -- |Unable to decrement reference count
+    | CantDec
+    -- |Out of IDs for group
+    | NoIds
+    -- |Unable to flush data from cache
+    | CantFlush
+    -- |Unable to serialize data from cache
+    | CantSerialize
+    -- |Unable to load metadata into cache
+    | CantLoad
+    -- |Protected metadata error
+    | Protect
+    -- |Metadata not currently cached
+    | NotCached
+    -- |Internal error detected
+    | System
+    -- |Unable to insert metadata into cache
+    | CantIns
+    -- |Unable to protect metadata
+    | CantProtect
+    -- |Unable to unprotect metadata
+    | CanTUnprotect
+    -- |Unable to pin cache entry
+    | CantPin
+    -- |Unable to un-pin cache entry
+    | CantUnpin
+    -- |Unable to mark a pinned entry as dirty
+    | CantMarkDirty
+    -- |Unable to mark metadata as dirty
+    | CantDirty
+    -- |Unable to expunge a metadata cache entry
+    | CantExpunge
+    -- |Unable to resize a metadata cache entry
+    | CantResize
+    -- |Link traversal failure
+    | Traverse
+    -- |Too many soft links in path
+    | NLinks
+    -- |Link class not registered
+    | NotRegistered
+    -- |Can't move object
+    | CantMove
+    -- |Can't sort objects
+    | CantSort
+    -- |Some MPI function failed
+    | MPI
+    -- |MPI Error String
+    | MPIErrStr
+    -- |Can't receive data
+    | CantRecv
+    -- |Can't clip hyperslab region
+    | CantClip
+    -- |Can't count elements
+    | CantCount
+    -- |Can't select hyperslab
+    | CantSelect
+    -- |Can't move to next iterator location
+    | CantNext
+    -- |Invalid selection
+    | BadSelect
+    -- |Can't compare objects
+    | CantCompare
+    -- |Information is uinitialized
+    | Uninitialized
+    -- |Feature is unsupported
+    | Unsupported
+    -- |Inappropriate type
+    | BadType
+    -- |Out of range
+    | BadRange
+    -- |Bad value
+    | BadValue
+    -- |Object not found
+    | NotFound
+    -- |Object already exists
+    | Exists
+    -- |Unable to encode value
+    | CantEncode
+    -- |Unable to decode value
+    | CantDecode
+    -- |Unable to split node
+    | CantSplit
+    -- |Unable to redistribute records
+    | CantRedistribute
+    -- |Unable to swap records
+    | CantSwap
+    -- |Unable to insert object
+    | CantInsert
+    -- |Unable to list node
+    | CantList
+    -- |Unable to modify record
+    | CantModify
+    -- |Unable to remove object
+    | CantRemove
+    -- |Can't convert datatypes
+    | CantConvert
+    -- |Bad size for object
+    | BadSize
+
+    -- |Unrecognized minor error code
+    | UnknownMinor HId_t
+    deriving (Eq, Ord, Show, Typeable)
+
+rawMinorErrCodesInv :: [(HId_t, Maybe MinorErrCode)]
+rawMinorErrCodesInv = [(a,b) | (b,a) <- rawMinorErrCodes]
+rawMinorErrCodes :: [(Maybe MinorErrCode, HId_t)]
+rawMinorErrCodes =
+    [ (Nothing,                 h5e_NONE_MINOR)
+    , (Just SeekError,          h5e_SEEKERROR)
+    , (Just ReadError,          h5e_READERROR)
+    , (Just WriteError,         h5e_WRITEERROR)
+    , (Just CloseError,         h5e_CLOSEERROR)
+    , (Just Overflow,           h5e_OVERFLOW)
+    , (Just FCNTL,              h5e_FCNTL)
+    , (Just NoSpace,            h5e_NOSPACE)
+    , (Just CantAlloc,          h5e_CANTALLOC)
+    , (Just CantCopy,           h5e_CANTCOPY)
+    , (Just CantFree,           h5e_CANTFREE)
+    , (Just AlreadyExists,      h5e_ALREADYEXISTS)
+    , (Just CantLock,           h5e_CANTLOCK)
+    , (Just CantUnlock,         h5e_CANTUNLOCK)
+    , (Just CantGC,             h5e_CANTGC)
+    , (Just CantGetSize,        h5e_CANTGETSIZE)
+    , (Just ObjOpen,            h5e_OBJOPEN)
+    , (Just CantRestore,        h5e_CANTRESTORE)
+    , (Just CantCompute,        h5e_CANTCOMPUTE)
+    , (Just CantExtend,         h5e_CANTEXTEND)
+    , (Just CantAttach,         h5e_CANTATTACH)
+    , (Just CantUpdate,         h5e_CANTUPDATE)
+    , (Just CantOperate,        h5e_CANTOPERATE)
+    , (Just CantInit,           h5e_CANTINIT)
+    , (Just AlreadyInit,        h5e_ALREADYINIT)
+    , (Just CantRelease,        h5e_CANTRELEASE)
+    , (Just CantGet,            h5e_CANTGET)
+    , (Just CantSet,            h5e_CANTSET)
+    , (Just DupClass,           h5e_DUPCLASS)
+    , (Just CantMerge,          h5e_CANTMERGE)
+    , (Just CantRevive,         h5e_CANTREVIVE)
+    , (Just CantShrink,         h5e_CANTSHRINK)
+    , (Just LinkCount,          h5e_LINKCOUNT)
+    , (Just Version,            h5e_VERSION)
+    , (Just Alignment,          h5e_ALIGNMENT)
+    , (Just BadMesg,            h5e_BADMESG)
+    , (Just CantDelete,         h5e_CANTDELETE)
+    , (Just BadIter,            h5e_BADITER)
+    , (Just CantPack,           h5e_CANTPACK)
+    , (Just CantReset,          h5e_CANTRESET)
+    , (Just CantRename,         h5e_CANTRENAME)
+    , (Just SysErrStr,          h5e_SYSERRSTR)
+    , (Just NoFilter,           h5e_NOFILTER)
+    , (Just Callback,           h5e_CALLBACK)
+    , (Just CanApply,           h5e_CANAPPLY)
+    , (Just SetLocal,           h5e_SETLOCAL)
+    , (Just NoEncoder,          h5e_NOENCODER)
+    , (Just CantFilter,         h5e_CANTFILTER)
+    , (Just CantOpenObj,        h5e_CANTOPENOBJ)
+    , (Just CantCloseObj,       h5e_CANTCLOSEOBJ)
+    , (Just CompLen,            h5e_COMPLEN)
+    , (Just Path,               h5e_PATH)
+    , (Just FileExists,         h5e_FILEEXISTS)
+    , (Just FileOpen,           h5e_FILEOPEN)
+    , (Just CantCreate,         h5e_CANTCREATE)
+    , (Just CantOpenFile,       h5e_CANTOPENFILE)
+    , (Just CantCloseFile,      h5e_CANTCLOSEFILE)
+    , (Just NotHDF5,            h5e_NOTHDF5)
+    , (Just BadFile,            h5e_BADFILE)
+    , (Just Truncated,          h5e_TRUNCATED)
+    , (Just Mount,              h5e_MOUNT)
+#if !H5_VERSION_GE(1,8,14)
+    , (Just BadAtom,            h5e_BADATOM)
+#endif
+    , (Just BadGroup,           h5e_BADGROUP)
+    , (Just CantRegister,       h5e_CANTREGISTER)
+    , (Just CantInc,            h5e_CANTINC)
+    , (Just CantDec,            h5e_CANTDEC)
+    , (Just NoIds,              h5e_NOIDS)
+    , (Just CantFlush,          h5e_CANTFLUSH)
+    , (Just CantSerialize,      h5e_CANTSERIALIZE)
+    , (Just CantLoad,           h5e_CANTLOAD)
+    , (Just Protect,            h5e_PROTECT)
+    , (Just NotCached,          h5e_NOTCACHED)
+    , (Just System,             h5e_SYSTEM)
+    , (Just CantIns,            h5e_CANTINS)
+    , (Just CantProtect,        h5e_CANTPROTECT)
+    , (Just CanTUnprotect,      h5e_CANTUNPROTECT)
+    , (Just CantPin,            h5e_CANTPIN)
+    , (Just CantUnpin,          h5e_CANTUNPIN)
+    , (Just CantMarkDirty,      h5e_CANTMARKDIRTY)
+    , (Just CantDirty,          h5e_CANTDIRTY)
+    , (Just CantExpunge,        h5e_CANTEXPUNGE)
+    , (Just CantResize,         h5e_CANTRESIZE)
+    , (Just Traverse,           h5e_TRAVERSE)
+    , (Just NLinks,             h5e_NLINKS)
+    , (Just NotRegistered,      h5e_NOTREGISTERED)
+    , (Just CantMove,           h5e_CANTMOVE)
+    , (Just CantSort,           h5e_CANTSORT)
+    , (Just MPI,                h5e_MPI)
+    , (Just MPIErrStr,          h5e_MPIERRSTR)
+    , (Just CantRecv,           h5e_CANTRECV)
+    , (Just CantClip,           h5e_CANTCLIP)
+    , (Just CantCount,          h5e_CANTCOUNT)
+    , (Just CantSelect,         h5e_CANTSELECT)
+    , (Just CantNext,           h5e_CANTNEXT)
+    , (Just BadSelect,          h5e_BADSELECT)
+    , (Just CantCompare,        h5e_CANTCOMPARE)
+    , (Just Uninitialized,      h5e_UNINITIALIZED)
+    , (Just Unsupported,        h5e_UNSUPPORTED)
+    , (Just BadType,            h5e_BADTYPE)
+    , (Just BadRange,           h5e_BADRANGE)
+    , (Just BadValue,           h5e_BADVALUE)
+    , (Just NotFound,           h5e_NOTFOUND)
+    , (Just Exists,             h5e_EXISTS)
+    , (Just CantEncode,         h5e_CANTENCODE)
+    , (Just CantDecode,         h5e_CANTDECODE)
+    , (Just CantSplit,          h5e_CANTSPLIT)
+    , (Just CantRedistribute,   h5e_CANTREDISTRIBUTE)
+    , (Just CantSwap,           h5e_CANTSWAP)
+    , (Just CantInsert,         h5e_CANTINSERT)
+    , (Just CantList,           h5e_CANTLIST)
+    , (Just CantModify,         h5e_CANTMODIFY)
+    , (Just CantRemove,         h5e_CANTREMOVE)
+    , (Just CantConvert,        h5e_CANTCONVERT)
+    , (Just BadSize,            h5e_BADSIZE)
+    ]
+
+minorErrorCode :: Maybe MinorErrCode -> Maybe HId_t
+minorErrorCode (Just (UnknownMinor code)) = Just code
+minorErrorCode err = lookup err rawMinorErrCodes
+
+minorErrorFromCode :: HId_t -> Maybe MinorErrCode
+minorErrorFromCode code =
+    fromMaybe (Just (UnknownMinor code))
+                  (lookup code rawMinorErrCodesInv)
+
+instance Storable (Maybe MinorErrCode) where
+    sizeOf    _ = sizeOf    (undefined :: HId_t)
+    alignment _ = alignment (undefined :: HId_t)
+
+    peek = fmap minorErrorFromCode . peek . castPtr
+    poke p err = case minorErrorCode err of
+        Nothing -> fail ("Unknown minor error code: " ++ show err)
+        Just code -> poke (castPtr p) code
diff --git a/src/Bindings/HDF5/File.hs b/src/Bindings/HDF5/File.hs
deleted file mode 100644
--- a/src/Bindings/HDF5/File.hs
+++ /dev/null
@@ -1,284 +0,0 @@
-{-# LANGUAGE GeneralizedNewtypeDeriving #-}
-{-# LANGUAGE FlexibleInstances #-}
-module Bindings.HDF5.File
-    ( AccFlags(..)
-    , ObjType(..)
-    , Scope(..)
-
-    , isHDF5
-
-    , File
-    , createFile
-    , openFile
-    , reopenFile
-    , flushFile
-    , closeFile
-
-    , mountFile
-    , unmountFile
-
-    , getFileSize
-    , getFileCreatePlist
-    , getFileAccessPlist
-
-    , FileInfo(..)
-    , getFileInfo
-    , getFileIntent
-    , getFileName
-    , getFileObjCount
-
-    , getOpenObjects
-    , getFileFreespace
---    , get_mdc_config
---    , get_mdc_hit_rate
---    , get_mdc_size
---    , clear_elink_file_cache
---    , reset_mdc_hit_rate_stats
---    , set_mdc_config
-    ) where
-
-import Bindings.HDF5.Core
-import Bindings.HDF5.Error
-import Bindings.HDF5.Object
-import Bindings.HDF5.PropertyList.FAPL
-import Bindings.HDF5.PropertyList.FCPL
-import Bindings.HDF5.PropertyList.FMPL
-import Bindings.HDF5.Raw.H5
-import Bindings.HDF5.Raw.H5F
-import Bindings.HDF5.Raw.H5I
-import Bindings.HDF5.Raw.H5P
-import Data.Bits
-import Data.Maybe
-import qualified Data.ByteString as BS
-import qualified Data.Vector.Storable as SV
-import Foreign.C
-import Foreign.Ptr
-import Foreign.Ptr.Conventions
-import Foreign.Storable
-
--- TODO: determine whether all of these are valid for _both_ create and open.
--- any that are not should be converted to Bool inputs to the corresponding function.
--- It very well may be best to separate several of them out like that anyway.
-data AccFlags
-    = ReadOnly
-    | ReadWrite
-    | Truncate
-    | FailIfExists
-    | Debug
-    | Create
-    deriving (Eq, Ord, Enum, Bounded, Read, Show)
-
-accFlagToInt :: AccFlags -> CUInt
-accFlagToInt ReadOnly       = h5f_ACC_RDONLY
-accFlagToInt ReadWrite      = h5f_ACC_RDWR
-accFlagToInt Truncate       = h5f_ACC_TRUNC
-accFlagToInt FailIfExists   = h5f_ACC_EXCL
-accFlagToInt Debug          = h5f_ACC_DEBUG
-accFlagToInt Create         = h5f_ACC_CREAT
-
-accFlagsToInt :: [AccFlags] -> CUInt
-accFlagsToInt = foldl (.|.) 0 . map accFlagToInt
-
-intToAccFlags :: CUInt -> [AccFlags]
-intToAccFlags x =
-    [ f
-    | f <- [minBound .. maxBound]
-    , accFlagToInt f .&. x /= 0
-    ]
-
-instance Storable [AccFlags] where
-    sizeOf    _ = sizeOf (0 :: CUInt)
-    alignment _ = alignment (0 :: CUInt)
-    peek        = fmap intToAccFlags . peek . castPtr
-    poke p      = poke (castPtr p) . accFlagsToInt
-
-data ObjType
-    = Files
-    | Datasets
-    | Groups
-    | Datatypes
-    | Attrs
-    | All
-    deriving (Eq, Ord, Enum, Bounded, Read, Show)
-
-objTypeToInt :: ObjType -> CUInt
-objTypeToInt Files      = h5f_OBJ_FILE
-objTypeToInt Datasets   = h5f_OBJ_DATASET
-objTypeToInt Groups     = h5f_OBJ_GROUP
-objTypeToInt Datatypes  = h5f_OBJ_DATATYPE
-objTypeToInt Attrs      = h5f_OBJ_ATTR
-objTypeToInt All        = h5f_OBJ_ALL
-
-objTypesToInt :: [ObjType] -> CUInt
-objTypesToInt = foldl (.|.) 0 . map objTypeToInt
-
-intToObjTypes :: CUInt -> [ObjType]
-intToObjTypes x =
-    [ f
-    | f <- [minBound .. maxBound]
-    , objTypeToInt f .&. x /= 0
-    ]
-
-instance Storable [ObjType] where
-    sizeOf    _ = sizeOf (0 :: CUInt)
-    alignment _ = alignment (0 :: CUInt)
-    peek        = fmap intToObjTypes . peek . castPtr
-    poke p      = poke (castPtr p) . objTypesToInt
-
-data Scope
-    = Local
-    | Global
-    deriving (Eq, Ord, Enum, Bounded, Read, Show)
-
-scopeCode :: Scope -> H5F_scope_t
-scopeCode Local  = h5f_SCOPE_LOCAL
-scopeCode Global = h5f_SCOPE_GLOBAL
-
-data CloseDegree
-    = Weak
-    | Semi
-    | Strong
-    deriving (Eq, Ord, Enum, Bounded, Read, Show)
-
-rawCloseDegreesInv :: [(H5F_close_degree_t, Maybe CloseDegree)]
-rawCloseDegreesInv = [(a,b) | (b,a) <- rawCloseDegrees]
-rawCloseDegrees :: [(Maybe CloseDegree, H5F_close_degree_t)]
-rawCloseDegrees =
-    [ (Nothing,     h5f_CLOSE_DEFAULT)
-    , (Just Weak,   h5f_CLOSE_WEAK)
-    , (Just Semi,   h5f_CLOSE_SEMI)
-    , (Just Strong, h5f_CLOSE_STRONG)
-    ]
-
-closeDegreeFromCode :: H5F_close_degree_t -> Maybe CloseDegree
-closeDegreeFromCode c = fromMaybe Nothing (lookup c rawCloseDegreesInv)
-
-closeDegreeToCode :: Maybe CloseDegree -> H5F_close_degree_t
-closeDegreeToCode c =
-    fromMaybe (error ("closeDegreeToCode: unrecognized H5F_close_degree_t: " ++ show c))
-                  (lookup c rawCloseDegrees)
-
-instance Storable (Maybe CloseDegree) where
-    sizeOf _    = sizeOf    (undefined :: H5F_close_degree_t)
-    alignment _ = alignment (undefined :: H5F_close_degree_t)
-    peek        = fmap closeDegreeFromCode . peek . castPtr
-    poke p      = poke (castPtr p) . closeDegreeToCode
-
-isHDF5 :: BS.ByteString -> IO Bool
-isHDF5 filename = htriToBool (BS.useAsCString filename h5f_is_hdf5)
-
-newtype File = File HId_t
-    deriving (Eq, HId, FromHId, HDFResultType)
-
-instance Location File
-instance Object File where
-    staticObjectType = Tagged (Just FileObj)
-
-createFile :: BS.ByteString -> [AccFlags] -> Maybe FCPL -> Maybe FAPL -> IO File
-createFile filename flags create_plist access_plist =
-    fmap File $
-        withErrorCheck $
-            BS.useAsCString filename $ \cfilename ->
-                h5f_create cfilename (accFlagsToInt flags) (maybe h5p_DEFAULT hid create_plist) (maybe h5p_DEFAULT hid access_plist)
-
-openFile :: BS.ByteString -> [AccFlags] -> Maybe FAPL -> IO File
-openFile filename flags access_plist =
-    fmap File $
-        withErrorCheck $
-            BS.useAsCString filename $ \cfilename ->
-                h5f_open cfilename (accFlagsToInt flags) (maybe h5p_DEFAULT hid access_plist)
-
-reopenFile :: File -> IO File
-reopenFile (File file_id) =
-    fmap File $
-        withErrorCheck $
-            h5f_reopen file_id
-
-flushFile :: File -> Scope -> IO ()
-flushFile (File file_id) scope =
-    withErrorCheck_ $
-        h5f_flush file_id (scopeCode scope)
-
-closeFile :: File -> IO ()
-closeFile (File file_id) =
-    withErrorCheck_ (h5f_close file_id)
-
-mountFile :: Location loc => loc -> BS.ByteString -> File -> Maybe FMPL -> IO ()
-mountFile loc groupname (File file_id) mount_plist =
-    withErrorCheck_ $
-        BS.useAsCString groupname $ \cgroupname ->
-            h5f_mount (hid loc) cgroupname file_id (maybe h5p_DEFAULT hid mount_plist)
-
-unmountFile :: Location loc => loc -> BS.ByteString -> IO ()
-unmountFile loc groupname =
-    withErrorCheck_ $
-        BS.useAsCString groupname $ \cgroupname ->
-            h5f_unmount (hid loc) cgroupname
-
-getFileSize :: File -> IO HSize
-getFileSize (File file_id) =
-    fmap HSize $
-        withOut_ $ \sz ->
-            withErrorCheck $
-                h5f_get_filesize file_id sz
-
-getFileCreatePlist :: File -> IO FCPL
-getFileCreatePlist (File file_id) =
-    fmap uncheckedFromHId $
-        withErrorCheck $
-            h5f_get_create_plist file_id
-
-getFileAccessPlist :: File -> IO FAPL
-getFileAccessPlist (File file_id) =
-    fmap uncheckedFromHId $
-        withErrorCheck $
-            h5f_get_access_plist file_id
-
-data FileInfo = FileInfo
-    { superExtSize  :: !HSize
-    , sohmHdrSize   :: !HSize
-    , sohmMsgsInfo  :: !IH_Info
-    } deriving (Eq, Ord, Read, Show)
-
-readFileInfo :: H5F_info_t -> FileInfo
-readFileInfo (H5F_info_t a b (H5_ih_info_t c d)) = FileInfo (HSize a) (HSize b) (IH_Info (HSize c) (HSize d))
-
-getFileInfo :: Object obj => obj -> IO FileInfo
-getFileInfo obj =
-    fmap readFileInfo $
-        withOut_ $ \info ->
-            withErrorCheck $
-                h5f_get_info (hid obj) info
-
-getFileIntent :: File -> IO [AccFlags]
-getFileIntent (File file_id) =
-    fmap intToAccFlags $
-        withOut_ $ \intent ->
-            withErrorCheck_ $
-                h5f_get_intent file_id intent
-
-getFileName :: File -> IO BS.ByteString
-getFileName (File file_id) =
-    withOutByteString' $ \buf bufSz ->
-        withErrorWhen (< 0) $
-            h5f_get_name file_id buf bufSz
-
-getFileObjCount :: Maybe File -> Bool -> [ObjType] -> IO CSize
-getFileObjCount mbFile local objTypes =
-    fmap fromIntegral $
-        withErrorWhen (< 0) $
-            h5f_get_obj_count (maybe (HId_t h5f_OBJ_ALL) hid mbFile) (objTypesToInt objTypes .|. if local then 0 else h5f_OBJ_LOCAL)
-
-getOpenObjects :: Maybe File -> Bool -> [ObjType] -> IO (SV.Vector ObjectId)
-getOpenObjects mbFile local objTypes = do
-    n <- getFileObjCount mbFile local objTypes
-
-    withOutVector' (fromIntegral n) $ \objects ->
-        withErrorWhen (< 0) $
-            h5f_get_obj_ids (maybe (HId_t h5f_OBJ_ALL) hid mbFile) (objTypesToInt objTypes .|. if local then 0 else h5f_OBJ_LOCAL) n (castWrappedPtr objects)
-
-getFileFreespace :: File -> IO HSize
-getFileFreespace (File file_id) =
-    fmap fromIntegral $
-        withErrorWhen (< 0) $
-            h5f_get_freespace file_id
diff --git a/src/Bindings/HDF5/File.hsc b/src/Bindings/HDF5/File.hsc
new file mode 100644
--- /dev/null
+++ b/src/Bindings/HDF5/File.hsc
@@ -0,0 +1,292 @@
+#include <bindings.h>
+#include <H5Fpublic.h>
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE FlexibleInstances #-}
+module Bindings.HDF5.File
+    ( AccFlags(..)
+    , ObjType(..)
+    , Scope(..)
+
+    , isHDF5
+
+    , File
+    , createFile
+    , openFile
+    , reopenFile
+    , flushFile
+    , closeFile
+
+    , mountFile
+    , unmountFile
+
+    , getFileSize
+    , getFileCreatePlist
+    , getFileAccessPlist
+
+    , FileInfo(..)
+    , getFileInfo
+    , getFileIntent
+    , getFileName
+    , getFileObjCount
+
+    , getOpenObjects
+    , getFileFreespace
+--    , get_mdc_config
+--    , get_mdc_hit_rate
+--    , get_mdc_size
+--    , clear_elink_file_cache
+--    , reset_mdc_hit_rate_stats
+--    , set_mdc_config
+    ) where
+
+import Bindings.HDF5.Core
+import Bindings.HDF5.Error
+import Bindings.HDF5.Object
+import Bindings.HDF5.PropertyList.FAPL
+import Bindings.HDF5.PropertyList.FCPL
+import Bindings.HDF5.PropertyList.FMPL
+import Bindings.HDF5.Raw.H5
+import Bindings.HDF5.Raw.H5F
+import Bindings.HDF5.Raw.H5I
+import Bindings.HDF5.Raw.H5P
+import Data.Bits
+import Data.Maybe
+import qualified Data.ByteString as BS
+import qualified Data.Vector.Storable as SV
+import Foreign.C
+import Foreign.Ptr
+import Foreign.Ptr.Conventions
+import Foreign.Storable
+
+-- TODO: determine whether all of these are valid for _both_ create and open.
+-- any that are not should be converted to Bool inputs to the corresponding function.
+-- It very well may be best to separate several of them out like that anyway.
+data AccFlags
+    = ReadOnly
+    | ReadWrite
+    | Truncate
+    | FailIfExists
+    | Debug
+    | Create
+    deriving (Eq, Ord, Enum, Bounded, Read, Show)
+
+accFlagToInt :: AccFlags -> CUInt
+accFlagToInt ReadOnly       = h5f_ACC_RDONLY
+accFlagToInt ReadWrite      = h5f_ACC_RDWR
+accFlagToInt Truncate       = h5f_ACC_TRUNC
+accFlagToInt FailIfExists   = h5f_ACC_EXCL
+accFlagToInt Debug          = h5f_ACC_DEBUG
+accFlagToInt Create         = h5f_ACC_CREAT
+
+accFlagsToInt :: [AccFlags] -> CUInt
+accFlagsToInt = foldl (.|.) 0 . map accFlagToInt
+
+intToAccFlags :: CUInt -> [AccFlags]
+intToAccFlags x =
+    [ f
+    | f <- [minBound .. maxBound]
+    , accFlagToInt f .&. x /= 0
+    ]
+
+instance Storable [AccFlags] where
+    sizeOf    _ = sizeOf (0 :: CUInt)
+    alignment _ = alignment (0 :: CUInt)
+    peek        = fmap intToAccFlags . peek . castPtr
+    poke p      = poke (castPtr p) . accFlagsToInt
+
+data ObjType
+    = Files
+    | Datasets
+    | Groups
+    | Datatypes
+    | Attrs
+    | All
+    deriving (Eq, Ord, Enum, Bounded, Read, Show)
+
+objTypeToInt :: ObjType -> CUInt
+objTypeToInt Files      = h5f_OBJ_FILE
+objTypeToInt Datasets   = h5f_OBJ_DATASET
+objTypeToInt Groups     = h5f_OBJ_GROUP
+objTypeToInt Datatypes  = h5f_OBJ_DATATYPE
+objTypeToInt Attrs      = h5f_OBJ_ATTR
+objTypeToInt All        = h5f_OBJ_ALL
+
+objTypesToInt :: [ObjType] -> CUInt
+objTypesToInt = foldl (.|.) 0 . map objTypeToInt
+
+intToObjTypes :: CUInt -> [ObjType]
+intToObjTypes x =
+    [ f
+    | f <- [minBound .. maxBound]
+    , objTypeToInt f .&. x /= 0
+    ]
+
+instance Storable [ObjType] where
+    sizeOf    _ = sizeOf (0 :: CUInt)
+    alignment _ = alignment (0 :: CUInt)
+    peek        = fmap intToObjTypes . peek . castPtr
+    poke p      = poke (castPtr p) . objTypesToInt
+
+data Scope
+    = Local
+    | Global
+    deriving (Eq, Ord, Enum, Bounded, Read, Show)
+
+scopeCode :: Scope -> H5F_scope_t
+scopeCode Local  = h5f_SCOPE_LOCAL
+scopeCode Global = h5f_SCOPE_GLOBAL
+
+data CloseDegree
+    = Weak
+    | Semi
+    | Strong
+    deriving (Eq, Ord, Enum, Bounded, Read, Show)
+
+rawCloseDegreesInv :: [(H5F_close_degree_t, Maybe CloseDegree)]
+rawCloseDegreesInv = [(a,b) | (b,a) <- rawCloseDegrees]
+rawCloseDegrees :: [(Maybe CloseDegree, H5F_close_degree_t)]
+rawCloseDegrees =
+    [ (Nothing,     h5f_CLOSE_DEFAULT)
+    , (Just Weak,   h5f_CLOSE_WEAK)
+    , (Just Semi,   h5f_CLOSE_SEMI)
+    , (Just Strong, h5f_CLOSE_STRONG)
+    ]
+
+closeDegreeFromCode :: H5F_close_degree_t -> Maybe CloseDegree
+closeDegreeFromCode c = fromMaybe Nothing (lookup c rawCloseDegreesInv)
+
+closeDegreeToCode :: Maybe CloseDegree -> H5F_close_degree_t
+closeDegreeToCode c =
+    fromMaybe (error ("closeDegreeToCode: unrecognized H5F_close_degree_t: " ++ show c))
+                  (lookup c rawCloseDegrees)
+
+instance Storable (Maybe CloseDegree) where
+    sizeOf _    = sizeOf    (undefined :: H5F_close_degree_t)
+    alignment _ = alignment (undefined :: H5F_close_degree_t)
+    peek        = fmap closeDegreeFromCode . peek . castPtr
+    poke p      = poke (castPtr p) . closeDegreeToCode
+
+isHDF5 :: BS.ByteString -> IO Bool
+isHDF5 filename = htriToBool (BS.useAsCString filename h5f_is_hdf5)
+
+newtype File = File HId_t
+    deriving (Eq, HId, FromHId, HDFResultType)
+
+instance Location File
+instance Object File where
+    staticObjectType = Tagged (Just FileObj)
+
+createFile :: BS.ByteString -> [AccFlags] -> Maybe FCPL -> Maybe FAPL -> IO File
+createFile filename flags create_plist access_plist =
+    fmap File $
+        withErrorCheck $
+            BS.useAsCString filename $ \cfilename ->
+                h5f_create cfilename (accFlagsToInt flags) (maybe h5p_DEFAULT hid create_plist) (maybe h5p_DEFAULT hid access_plist)
+
+openFile :: BS.ByteString -> [AccFlags] -> Maybe FAPL -> IO File
+openFile filename flags access_plist =
+    fmap File $
+        withErrorCheck $
+            BS.useAsCString filename $ \cfilename ->
+                h5f_open cfilename (accFlagsToInt flags) (maybe h5p_DEFAULT hid access_plist)
+
+reopenFile :: File -> IO File
+reopenFile (File file_id) =
+    fmap File $
+        withErrorCheck $
+            h5f_reopen file_id
+
+flushFile :: File -> Scope -> IO ()
+flushFile (File file_id) scope =
+    withErrorCheck_ $
+        h5f_flush file_id (scopeCode scope)
+
+closeFile :: File -> IO ()
+closeFile (File file_id) =
+    withErrorCheck_ (h5f_close file_id)
+
+mountFile :: Location loc => loc -> BS.ByteString -> File -> Maybe FMPL -> IO ()
+mountFile loc groupname (File file_id) mount_plist =
+    withErrorCheck_ $
+        BS.useAsCString groupname $ \cgroupname ->
+            h5f_mount (hid loc) cgroupname file_id (maybe h5p_DEFAULT hid mount_plist)
+
+unmountFile :: Location loc => loc -> BS.ByteString -> IO ()
+unmountFile loc groupname =
+    withErrorCheck_ $
+        BS.useAsCString groupname $ \cgroupname ->
+            h5f_unmount (hid loc) cgroupname
+
+getFileSize :: File -> IO HSize
+getFileSize (File file_id) =
+    fmap HSize $
+        withOut_ $ \sz ->
+            withErrorCheck $
+                h5f_get_filesize file_id sz
+
+getFileCreatePlist :: File -> IO FCPL
+getFileCreatePlist (File file_id) =
+    fmap uncheckedFromHId $
+        withErrorCheck $
+            h5f_get_create_plist file_id
+
+getFileAccessPlist :: File -> IO FAPL
+getFileAccessPlist (File file_id) =
+    fmap uncheckedFromHId $
+        withErrorCheck $
+            h5f_get_access_plist file_id
+
+data FileInfo = FileInfo
+    { superExtSize  :: !HSize
+    , sohmHdrSize   :: !HSize
+    , sohmMsgsInfo  :: !IH_Info
+    } deriving (Eq, Ord, Read, Show)
+
+readFileInfo :: H5F_info_t -> FileInfo
+#if H5Fget_info_vers == 1
+readFileInfo (H5F_info_t a b (H5_ih_info_t c d)) = FileInfo (HSize a) (HSize b) (IH_Info (HSize c) (HSize d))
+#elif H5Fget_info_vers == 2
+readFileInfo (H5F_info_t _superVersion _superSize superExtSize' _freeVersion _metaSize _totSpace _sohmVersion sohmHdrSize' (H5_ih_info_t c d)) = FileInfo (HSize superExtSize') (HSize sohmHdrSize') (IH_Info (HSize c) (HSize d))
+#else
+#error unknown H5Fget_info_vers
+#endif
+
+getFileInfo :: Object obj => obj -> IO FileInfo
+getFileInfo obj =
+    fmap readFileInfo $
+        withOut_ $ \info ->
+            withErrorCheck $
+                h5f_get_info (hid obj) info
+
+getFileIntent :: File -> IO [AccFlags]
+getFileIntent (File file_id) =
+    fmap intToAccFlags $
+        withOut_ $ \intent ->
+            withErrorCheck_ $
+                h5f_get_intent file_id intent
+
+getFileName :: File -> IO BS.ByteString
+getFileName (File file_id) =
+    withOutByteString' $ \buf bufSz ->
+        withErrorWhen (< 0) $
+            h5f_get_name file_id buf bufSz
+
+getFileObjCount :: Maybe File -> Bool -> [ObjType] -> IO CSize
+getFileObjCount mbFile local objTypes =
+    fmap fromIntegral $
+        withErrorWhen (< 0) $
+            h5f_get_obj_count (maybe (HId_t h5f_OBJ_ALL) hid mbFile) (objTypesToInt objTypes .|. if local then 0 else h5f_OBJ_LOCAL)
+
+getOpenObjects :: Maybe File -> Bool -> [ObjType] -> IO (SV.Vector ObjectId)
+getOpenObjects mbFile local objTypes = do
+    n <- getFileObjCount mbFile local objTypes
+
+    withOutVector' (fromIntegral n) $ \objects ->
+        withErrorWhen (< 0) $
+            h5f_get_obj_ids (maybe (HId_t h5f_OBJ_ALL) hid mbFile) (objTypesToInt objTypes .|. if local then 0 else h5f_OBJ_LOCAL) n (castWrappedPtr objects)
+
+getFileFreespace :: File -> IO HSize
+getFileFreespace (File file_id) =
+    fmap fromIntegral $
+        withErrorWhen (< 0) $
+            h5f_get_freespace file_id
diff --git a/src/Bindings/HDF5/Link.hs b/src/Bindings/HDF5/Link.hs
deleted file mode 100644
--- a/src/Bindings/HDF5/Link.hs
+++ /dev/null
@@ -1,258 +0,0 @@
-{-# LANGUAGE ForeignFunctionInterface #-}
-{-
-
-  h5l_get_info_by_idx           	[ FAIL ]
-  h5l_iterate                   	[  OK  ]
-  h5l_register                  	[ FAIL ]
-  h5l_iterate_by_name           	[  OK  ]
-  h5l_unpack_elink_val          	[ FAIL ]
-  h5l_get_val_by_idx            	[ FAIL ]
-  h5l_create_external           	[  OK  ]
-  h5l_exists                    	[  OK  ]
-  h5l_move                      	[  OK  ]
-  h5l_create_ud                 	[ FAIL ]
-  h5l_create_hard               	[  OK  ]
-  h5l_is_registered             	[ FAIL ]
-  h5l_get_name_by_idx           	[  OK  ]
-  h5l_create_soft               	[  OK  ]
-  h5l_copy                      	[  OK  ]
-  h5l_get_val                   	[  OK  ]
-  h5l_visit                     	[  OK  ]
-  h5l_get_info                  	[  OK  ]
-  h5l_delete_by_idx             	[ FAIL ]
-  h5l_visit_by_name             	[  OK  ]
-  h5l_delete                    	[  OK  ]
-  h5l_unregister                	[ FAIL ]
-
--}
-module Bindings.HDF5.Link
-    ( createHardLink
-    , createSoftLink
-    , createExternalLink
-
-    , getLinkNameByIdx
-
-    , doesLinkExist
-
-    , moveLink
-    , copyLink
-    , deleteLink
-
-    , LinkType(..)
-    , LinkInfo(..)
-    , getLinkInfo
-
-    , getSymLinkVal
-
-    , iterateLinks
-    , iterateLinksByName
-
-    , visitLinks
-    , visitLinksByName
-    ) where
-
-import           Bindings.HDF5.Core
-import           Bindings.HDF5.Datatype.Internal
-import           Bindings.HDF5.Error
-import           Bindings.HDF5.Group
-import           Bindings.HDF5.PropertyList.LAPL
-import           Bindings.HDF5.PropertyList.LCPL
-import           Bindings.HDF5.Raw.H5
-import           Bindings.HDF5.Raw.H5I
-import           Bindings.HDF5.Raw.H5L
-import           Bindings.HDF5.Raw.H5P
-import           Bindings.HDF5.Raw.Util
-import           Control.Exception               (SomeException, finally,
-                                                  throwIO, try)
-import qualified Data.ByteString                 as BS
-import           Data.IORef
-import           Foreign
-import           Foreign.C
-import           Foreign.Ptr.Conventions
-
-{-# ANN module "HLint: ignore Use camelCase" #-}
-
-createHardLink :: (Location src, Location dst) => src -> BS.ByteString -> dst -> BS.ByteString -> Maybe LCPL -> Maybe LAPL -> IO ()
-createHardLink src srcName dst dstName lcpl lapl =
-    withErrorCheck_ $
-        BS.useAsCString srcName $ \csrcName ->
-            BS.useAsCString dstName $ \cdstName ->
-                h5l_create_hard (hid src) csrcName (hid dst) cdstName
-                    (maybe h5p_DEFAULT hid lcpl)
-                    (maybe h5p_DEFAULT hid lapl)
-
-createSoftLink :: Location dst => BS.ByteString -> dst -> BS.ByteString -> Maybe LCPL -> Maybe LAPL -> IO ()
-createSoftLink srcName dst dstName lcpl lapl =
-    withErrorCheck_ $
-        BS.useAsCString srcName $ \csrcName ->
-            BS.useAsCString dstName $ \cdstName ->
-                h5l_create_soft csrcName (hid dst) cdstName
-                    (maybe h5p_DEFAULT hid lcpl)
-                    (maybe h5p_DEFAULT hid lapl)
-
-createExternalLink :: Location loc => BS.ByteString -> BS.ByteString -> loc -> BS.ByteString -> Maybe LCPL -> Maybe LAPL -> IO ()
-createExternalLink file obj loc name lcpl lapl =
-    withErrorCheck_ $
-        BS.useAsCString file $ \cfile ->
-            BS.useAsCString obj $ \cobj ->
-                BS.useAsCString name $ \cname ->
-                    h5l_create_external cfile cobj (hid loc) cname (maybe h5p_DEFAULT hid lcpl) (maybe h5p_DEFAULT hid lapl)
-
-getLinkNameByIdx :: Location loc =>  loc -> BS.ByteString -> IndexType -> IterOrder -> HSize -> Maybe LAPL -> IO BS.ByteString
-getLinkNameByIdx loc group indexType order idx lapl =
-  withOutByteString' $ \cname nameSize ->
-  BS.useAsCString group $ \cgroup ->
-  h5l_get_name_by_idx (hid loc) cgroup (indexTypeCode indexType) (iterOrderCode order) (hSize idx) cname nameSize (maybe h5p_DEFAULT hid lapl)
-
-doesLinkExist :: Location loc => loc -> BS.ByteString -> Maybe LAPL -> IO Bool
-doesLinkExist loc name lapl =
-    htriToBool $
-        BS.useAsCString name $ \cname ->
-            h5l_exists (hid loc) cname (maybe h5p_DEFAULT hid lapl)
-
-moveLink :: (Location src, Location dst) => src -> BS.ByteString -> dst -> BS.ByteString -> Maybe LCPL -> Maybe LAPL -> IO ()
-moveLink  src srcName dst dstName lcpl lapl =
-    withErrorCheck_ $
-        BS.useAsCString srcName $ \csrcName ->
-            BS.useAsCString dstName $ \cdstName ->
-                h5l_move (hid src) csrcName (hid dst) cdstName
-                    (maybe h5p_DEFAULT hid lcpl)
-                    (maybe h5p_DEFAULT hid lapl)
-
-copyLink :: (Location src, Location dst) => src -> BS.ByteString -> dst -> BS.ByteString -> Maybe LCPL -> Maybe LAPL -> IO ()
-copyLink  src srcName dst dstName lcpl lapl =
-    withErrorCheck_ $
-        BS.useAsCString srcName $ \csrcName ->
-            BS.useAsCString dstName $ \cdstName ->
-                h5l_copy (hid src) csrcName (hid dst) cdstName
-                    (maybe h5p_DEFAULT hid lcpl)
-                    (maybe h5p_DEFAULT hid lapl)
-
-deleteLink :: Location t => t -> BS.ByteString -> Maybe LAPL -> IO ()
-deleteLink loc name lapl =
-    withErrorCheck_ $
-        BS.useAsCString name $ \cname ->
-            h5l_delete (hid loc) cname (maybe h5p_DEFAULT hid lapl)
-
-data LinkType
-    = External
-    | Hard
-    | Soft
-    | OtherLinkType !H5L_type_t
-    deriving (Eq, Ord, Read, Show)
-
-linkTypeFromCode :: H5L_type_t -> LinkType
-linkTypeFromCode c
-    | c == h5l_TYPE_EXTERNAL    = External
-    | c == h5l_TYPE_HARD        = Hard
-    | c == h5l_TYPE_SOFT        = Soft
-    | c >= h5l_TYPE_UD_MIN      = OtherLinkType c
-    | otherwise                 = error ("Unknown link type: " ++ show c)
-
-
-data LinkInfo = LinkInfo
-    { linkType        :: LinkType
-    , linkCOrderValid :: Bool
-    , linkCOrder      :: Int64
-    , linkCSet        :: CSet
-    , linkAddress     :: HAddr
-    , linkValSize     :: CSize
-    } deriving (Eq, Ord, Read, Show)
-
-readLinkInfo :: H5L_info_t -> LinkInfo
-readLinkInfo i  = LinkInfo
-    { linkType          = linkTypeFromCode (h5l_info_t'type i)
-    , linkCOrderValid   = hboolToBool (h5l_info_t'corder_valid i)
-    , linkCOrder        = h5l_info_t'corder i
-    , linkCSet          = cSetFromCode (h5l_info_t'cset i)
-    , linkAddress       = HAddr (h5l_info_t'u'address i)
-    , linkValSize       = h5l_info_t'u'val_size i
-    }
-
-getLinkInfo :: Location loc => loc -> BS.ByteString -> Maybe LAPL -> IO LinkInfo
-getLinkInfo loc name lapl =
-    fmap readLinkInfo $
-        withOut_ $ \info ->
-            withErrorCheck_ $
-                BS.useAsCString name $ \cname ->
-                    h5l_get_info (hid loc) cname info (maybe h5p_DEFAULT hid lapl)
-
-getSymLinkVal :: Location loc => loc -> BS.ByteString -> Maybe LAPL -> IO BS.ByteString
-getSymLinkVal loc name mb_lapl =
-    BS.useAsCString name $ \cname -> do
-        let lapl = maybe h5p_DEFAULT hid mb_lapl
-        info <- withOut_ $ \info ->
-            withErrorCheck_ $
-                    h5l_get_info (hid loc) cname info lapl
-
-        let n = h5l_info_t'u'val_size info
-
-        buf <- mallocBytes (fromIntegral n)
-
-        withErrorCheck_ $
-            h5l_get_val (hid loc) cname (OutArray buf) n lapl
-        -- TODO: this will leak memory if an exception is thrown
-
-        BS.packCStringLen (buf, fromIntegral n)
-
-
-foreign import ccall "wrapper" wrap_H5L_iterate_t
-    :: (HId_t -> CString -> In H5L_info_t -> InOut a -> IO HErr_t)
-    -> IO (FunPtr (HId_t -> CString -> In H5L_info_t -> InOut a -> IO HErr_t))
-
-with_iterate_t :: (Group -> BS.ByteString -> LinkInfo -> IO HErr_t)
-     -> (H5L_iterate_t () -> InOut () -> IO HErr_t)
-     -> IO HErr_t
-with_iterate_t op f = do
-    exception1 <- newIORef Nothing :: IO (IORef (Maybe SomeException))
-
-    op1 <- wrap_H5L_iterate_t $ \grp name (In link) _opData -> do
-        name1 <- BS.packCString name
-        link1 <- peek link
-        result <- try (op (uncheckedFromHId grp) name1 (readLinkInfo link1))
-        case result of
-            Left exc -> do
-                writeIORef exception1 (Just exc)
-                return maxBound
-            Right x -> return x
-
-    result <- f op1 (InOut nullPtr) `finally` freeHaskellFunPtr op1
-
-    if result == maxBound
-        then do
-            exception2 <- readIORef exception1
-            maybe (return result) throwIO exception2
-
-        else return result
-
--- TODO : It would be nice if we didn't expose HErr_t in these callback functions.
---        Decide whether we want Either or Exceptions.
-iterateLinks :: Location t => t -> IndexType -> IterOrder -> Maybe HSize -> (Group -> BS.ByteString -> LinkInfo -> IO HErr_t) -> IO HSize
-iterateLinks loc indexType order startIndex op =
-    fmap HSize $
-        withInOut_ (maybe 0 hSize startIndex) $ \ioStartIndex ->
-            withErrorCheck_ $
-                with_iterate_t op $ \iop opData ->
-                    h5l_iterate (hid loc) (indexTypeCode indexType) (iterOrderCode order) ioStartIndex iop opData
-
-iterateLinksByName :: Location t => t -> BS.ByteString -> IndexType -> IterOrder -> Maybe HSize -> Maybe LAPL -> (Group -> BS.ByteString -> LinkInfo -> IO HErr_t) -> IO HSize
-iterateLinksByName loc groupName indexType order startIndex lapl op =
-    fmap HSize $
-        withInOut_ (maybe 0 hSize startIndex) $ \ioStartIndex ->
-            withErrorCheck_ $
-                with_iterate_t op $ \iop opData ->
-                    BS.useAsCString groupName $ \cgroupName ->
-                        h5l_iterate_by_name (hid loc) cgroupName (indexTypeCode indexType) (iterOrderCode order) ioStartIndex iop opData (maybe h5p_DEFAULT hid lapl)
-
-visitLinks :: Location t => t -> IndexType -> IterOrder -> (Group -> BS.ByteString -> LinkInfo -> IO HErr_t) -> IO ()
-visitLinks loc indexType order op =
-    withErrorCheck_ $
-        with_iterate_t op $ \iop opData ->
-            h5l_visit (hid loc) (indexTypeCode indexType) (iterOrderCode order) iop opData
-
-visitLinksByName :: Location t => t -> BS.ByteString -> IndexType -> IterOrder -> Maybe LAPL -> (Group -> BS.ByteString -> LinkInfo -> IO HErr_t) -> IO ()
-visitLinksByName loc groupName indexType order lapl op =
-    withErrorCheck_ $
-        with_iterate_t op $ \iop opData ->
-            BS.useAsCString groupName $ \cgroupName ->
-                h5l_visit_by_name (hid loc) cgroupName (indexTypeCode indexType) (iterOrderCode order) iop opData (maybe h5p_DEFAULT hid lapl)
diff --git a/src/Bindings/HDF5/Link.hsc b/src/Bindings/HDF5/Link.hsc
new file mode 100644
--- /dev/null
+++ b/src/Bindings/HDF5/Link.hsc
@@ -0,0 +1,304 @@
+#include <bindings.h>
+#include <H5Lpublic.h>
+#include <H5version.h>
+#if H5_VERSION_GE(1,14,0)
+#include <H5Ldevelop.h>
+#endif
+{-# LANGUAGE ForeignFunctionInterface #-}
+{-# LANGUAGE CPP #-}
+{-
+
+  h5l_get_info_by_idx           	[ FAIL ]
+  h5l_iterate                   	[  OK  ]
+  h5l_register                  	[ FAIL ]
+  h5l_iterate_by_name           	[  OK  ]
+  h5l_unpack_elink_val          	[ FAIL ]
+  h5l_get_val_by_idx            	[ FAIL ]
+  h5l_create_external           	[  OK  ]
+  h5l_exists                    	[  OK  ]
+  h5l_move                      	[  OK  ]
+  h5l_create_ud                 	[ FAIL ]
+  h5l_create_hard               	[  OK  ]
+  h5l_is_registered             	[ FAIL ]
+  h5l_get_name_by_idx           	[  OK  ]
+  h5l_create_soft               	[  OK  ]
+  h5l_copy                      	[  OK  ]
+  h5l_get_val                   	[  OK  ]
+  h5l_visit                     	[  OK  ]
+  h5l_get_info                  	[  OK  ]
+  h5l_delete_by_idx             	[ FAIL ]
+  h5l_visit_by_name             	[  OK  ]
+  h5l_delete                    	[  OK  ]
+  h5l_unregister                	[ FAIL ]
+
+-}
+module Bindings.HDF5.Link
+    ( createHardLink
+    , createSoftLink
+    , createExternalLink
+
+    , getLinkNameByIdx
+
+    , doesLinkExist
+
+    , moveLink
+    , copyLink
+    , deleteLink
+
+    , LinkType(..)
+    , LinkInfo(..)
+    , getLinkInfo
+
+    , getSymLinkVal
+
+    , iterateLinks
+    , iterateLinksByName
+
+    , visitLinks
+    , visitLinksByName
+    ) where
+
+import           Bindings.HDF5.Core
+import           Bindings.HDF5.Datatype.Internal
+import           Bindings.HDF5.Error
+import           Bindings.HDF5.Group
+import           Bindings.HDF5.PropertyList.LAPL
+import           Bindings.HDF5.PropertyList.LCPL
+import           Bindings.HDF5.Raw.H5
+import           Bindings.HDF5.Raw.H5I
+import           Bindings.HDF5.Raw.H5L
+import           Bindings.HDF5.Raw.H5P
+import           Bindings.HDF5.Raw.Util
+import           Control.Exception               (SomeException, finally,
+                                                  throwIO, try)
+import qualified Data.ByteString                 as BS
+import           Data.IORef
+import           Foreign
+import           Foreign.C
+import           Foreign.Ptr.Conventions
+
+{-# ANN module "HLint: ignore Use camelCase" #-}
+
+createHardLink :: (Location src, Location dst) => src -> BS.ByteString -> dst -> BS.ByteString -> Maybe LCPL -> Maybe LAPL -> IO ()
+createHardLink src srcName dst dstName lcpl lapl =
+    withErrorCheck_ $
+        BS.useAsCString srcName $ \csrcName ->
+            BS.useAsCString dstName $ \cdstName ->
+                h5l_create_hard (hid src) csrcName (hid dst) cdstName
+                    (maybe h5p_DEFAULT hid lcpl)
+                    (maybe h5p_DEFAULT hid lapl)
+
+createSoftLink :: Location dst => BS.ByteString -> dst -> BS.ByteString -> Maybe LCPL -> Maybe LAPL -> IO ()
+createSoftLink srcName dst dstName lcpl lapl =
+    withErrorCheck_ $
+        BS.useAsCString srcName $ \csrcName ->
+            BS.useAsCString dstName $ \cdstName ->
+                h5l_create_soft csrcName (hid dst) cdstName
+                    (maybe h5p_DEFAULT hid lcpl)
+                    (maybe h5p_DEFAULT hid lapl)
+
+createExternalLink :: Location loc => BS.ByteString -> BS.ByteString -> loc -> BS.ByteString -> Maybe LCPL -> Maybe LAPL -> IO ()
+createExternalLink file obj loc name lcpl lapl =
+    withErrorCheck_ $
+        BS.useAsCString file $ \cfile ->
+            BS.useAsCString obj $ \cobj ->
+                BS.useAsCString name $ \cname ->
+                    h5l_create_external cfile cobj (hid loc) cname (maybe h5p_DEFAULT hid lcpl) (maybe h5p_DEFAULT hid lapl)
+
+getLinkNameByIdx :: Location loc =>  loc -> BS.ByteString -> IndexType -> IterOrder -> HSize -> Maybe LAPL -> IO BS.ByteString
+getLinkNameByIdx loc group indexType order idx lapl =
+  withOutByteString' $ \cname nameSize ->
+  BS.useAsCString group $ \cgroup ->
+  h5l_get_name_by_idx (hid loc) cgroup (indexTypeCode indexType) (iterOrderCode order) (hSize idx) cname nameSize (maybe h5p_DEFAULT hid lapl)
+
+doesLinkExist :: Location loc => loc -> BS.ByteString -> Maybe LAPL -> IO Bool
+doesLinkExist loc name lapl =
+    htriToBool $
+        BS.useAsCString name $ \cname ->
+            h5l_exists (hid loc) cname (maybe h5p_DEFAULT hid lapl)
+
+moveLink :: (Location src, Location dst) => src -> BS.ByteString -> dst -> BS.ByteString -> Maybe LCPL -> Maybe LAPL -> IO ()
+moveLink  src srcName dst dstName lcpl lapl =
+    withErrorCheck_ $
+        BS.useAsCString srcName $ \csrcName ->
+            BS.useAsCString dstName $ \cdstName ->
+                h5l_move (hid src) csrcName (hid dst) cdstName
+                    (maybe h5p_DEFAULT hid lcpl)
+                    (maybe h5p_DEFAULT hid lapl)
+
+copyLink :: (Location src, Location dst) => src -> BS.ByteString -> dst -> BS.ByteString -> Maybe LCPL -> Maybe LAPL -> IO ()
+copyLink  src srcName dst dstName lcpl lapl =
+    withErrorCheck_ $
+        BS.useAsCString srcName $ \csrcName ->
+            BS.useAsCString dstName $ \cdstName ->
+                h5l_copy (hid src) csrcName (hid dst) cdstName
+                    (maybe h5p_DEFAULT hid lcpl)
+                    (maybe h5p_DEFAULT hid lapl)
+
+deleteLink :: Location t => t -> BS.ByteString -> Maybe LAPL -> IO ()
+deleteLink loc name lapl =
+    withErrorCheck_ $
+        BS.useAsCString name $ \cname ->
+            h5l_delete (hid loc) cname (maybe h5p_DEFAULT hid lapl)
+
+data LinkType
+    = External
+    | Hard
+    | Soft
+    | OtherLinkType !H5L_type_t
+    deriving (Eq, Ord, Read, Show)
+
+linkTypeFromCode :: H5L_type_t -> LinkType
+linkTypeFromCode c
+    | c == h5l_TYPE_EXTERNAL    = External
+    | c == h5l_TYPE_HARD        = Hard
+    | c == h5l_TYPE_SOFT        = Soft
+    | c >= h5l_TYPE_UD_MIN      = OtherLinkType c
+    | otherwise                 = error ("Unknown link type: " ++ show c)
+
+
+data LinkInfo = LinkInfo
+    { linkType        :: LinkType
+    , linkCOrderValid :: Bool
+    , linkCOrder      :: Int64
+    , linkCSet        :: CSet
+    , linkValSize     :: CSize
+    } deriving (Eq, Ord, Read, Show)
+
+#if H5Fget_info_vers == 1
+readLinkInfo :: H5L_info_t -> LinkInfo
+readLinkInfo i  = LinkInfo
+    { linkType          = linkTypeFromCode (h5l_info_t'type i)
+    , linkCOrderValid   = hboolToBool (h5l_info_t'corder_valid i)
+    , linkCOrder        = h5l_info_t'corder i
+    , linkCSet          = cSetFromCode (h5l_info_t'cset i)
+    , linkValSize       = h5l_info_t'u'val_size i
+    }
+#elif H5Fget_info_vers == 2
+readLinkInfo :: H5L_info_t -> LinkInfo
+readLinkInfo i  = LinkInfo
+    { linkType          = linkTypeFromCode (h5l_info2_t'type i)
+    , linkCOrderValid   = hboolToBool (h5l_info2_t'corder_valid i)
+    , linkCOrder        = h5l_info2_t'corder i
+    , linkCSet          = cSetFromCode (h5l_info2_t'cset i)
+    , linkValSize       = h5l_info2_t'u'val_size i
+    }
+#else
+#error "unknown info vers"
+#endif
+
+getLinkInfo :: Location loc => loc -> BS.ByteString -> Maybe LAPL -> IO LinkInfo
+getLinkInfo loc name lapl =
+    fmap readLinkInfo $
+        withOut_ $ \info ->
+            withErrorCheck_ $
+                BS.useAsCString name $ \cname ->
+#if (H5Fget_info_vers == 1)
+                    h5l_get_info (hid loc) cname info (maybe h5p_DEFAULT hid lapl)
+#else
+                    h5l_get_info2 (hid loc) cname info (maybe h5p_DEFAULT hid lapl)
+#endif
+
+getSymLinkVal :: Location loc => loc -> BS.ByteString -> Maybe LAPL -> IO BS.ByteString
+getSymLinkVal loc name mb_lapl =
+    BS.useAsCString name $ \cname -> do
+        let lapl = maybe h5p_DEFAULT hid mb_lapl
+        info <- withOut_ $ \info ->
+            withErrorCheck_ $
+#if (H5Fget_info_vers == 1)
+                    h5l_get_info (hid loc) cname info lapl
+#else
+                    h5l_get_info2 (hid loc) cname info lapl
+#endif
+
+#if (H5Fget_info_vers == 1)
+        let n = h5l_info_t'u'val_size info
+#else
+        let n = h5l_info2_t'u'val_size info
+#endif
+
+        buf <- mallocBytes (fromIntegral n)
+
+        withErrorCheck_ $
+            h5l_get_val (hid loc) cname (OutArray buf) n lapl
+        -- TODO: this will leak memory if an exception is thrown
+
+        BS.packCStringLen (buf, fromIntegral n)
+
+
+foreign import ccall "wrapper" wrap_H5L_iterate_t
+    :: (HId_t -> CString -> In H5L_info_t -> InOut a -> IO HErr_t)
+    -> IO (FunPtr (HId_t -> CString -> In H5L_info_t -> InOut a -> IO HErr_t))
+
+with_iterate_t :: (Group -> BS.ByteString -> LinkInfo -> IO HErr_t)
+     -> (H5L_iterate_t () -> InOut () -> IO HErr_t)
+     -> IO HErr_t
+with_iterate_t op f = do
+    exception1 <- newIORef Nothing :: IO (IORef (Maybe SomeException))
+
+    op1 <- wrap_H5L_iterate_t $ \grp name (In link) _opData -> do
+        name1 <- BS.packCString name
+        link1 <- peek link
+        result <- try (op (uncheckedFromHId grp) name1 (readLinkInfo link1))
+        case result of
+            Left exc -> do
+                writeIORef exception1 (Just exc)
+                return maxBound
+            Right x -> return x
+
+    result <- f op1 (InOut nullPtr) `finally` freeHaskellFunPtr op1
+
+    if result == maxBound
+        then do
+            exception2 <- readIORef exception1
+            maybe (return result) throwIO exception2
+
+        else return result
+
+-- TODO : It would be nice if we didn't expose HErr_t in these callback functions.
+--        Decide whether we want Either or Exceptions.
+iterateLinks :: Location t => t -> IndexType -> IterOrder -> Maybe HSize -> (Group -> BS.ByteString -> LinkInfo -> IO HErr_t) -> IO HSize
+iterateLinks loc indexType order startIndex op =
+    fmap HSize $
+        withInOut_ (maybe 0 hSize startIndex) $ \ioStartIndex ->
+            withErrorCheck_ $
+                with_iterate_t op $ \iop opData ->
+#if (H5Fget_info_vers == 1)
+                    h5l_iterate (hid loc) (indexTypeCode indexType) (iterOrderCode order) ioStartIndex iop opData
+#else
+                    h5l_iterate2 (hid loc) (indexTypeCode indexType) (iterOrderCode order) ioStartIndex iop opData
+#endif
+
+iterateLinksByName :: Location t => t -> BS.ByteString -> IndexType -> IterOrder -> Maybe HSize -> Maybe LAPL -> (Group -> BS.ByteString -> LinkInfo -> IO HErr_t) -> IO HSize
+iterateLinksByName loc groupName indexType order startIndex lapl op =
+    fmap HSize $
+        withInOut_ (maybe 0 hSize startIndex) $ \ioStartIndex ->
+            withErrorCheck_ $
+                with_iterate_t op $ \iop opData ->
+                    BS.useAsCString groupName $ \cgroupName ->
+#if (H5Fget_info_vers == 1)
+                        h5l_iterate_by_name (hid loc) cgroupName (indexTypeCode indexType) (iterOrderCode order) ioStartIndex iop opData (maybe h5p_DEFAULT hid lapl)
+#else
+                        h5l_iterate_by_name2 (hid loc) cgroupName (indexTypeCode indexType) (iterOrderCode order) ioStartIndex iop opData (maybe h5p_DEFAULT hid lapl)
+#endif
+
+visitLinks :: Location t => t -> IndexType -> IterOrder -> (Group -> BS.ByteString -> LinkInfo -> IO HErr_t) -> IO ()
+visitLinks loc indexType order op =
+    withErrorCheck_ $
+        with_iterate_t op $ \iop opData ->
+#if (H5Fget_info_vers == 1)
+            h5l_visit (hid loc) (indexTypeCode indexType) (iterOrderCode order) iop opData
+#else
+            h5l_visit2 (hid loc) (indexTypeCode indexType) (iterOrderCode order) iop opData
+#endif
+
+visitLinksByName :: Location t => t -> BS.ByteString -> IndexType -> IterOrder -> Maybe LAPL -> (Group -> BS.ByteString -> LinkInfo -> IO HErr_t) -> IO ()
+visitLinksByName loc groupName indexType order lapl op =
+    withErrorCheck_ $
+        with_iterate_t op $ \iop opData ->
+            BS.useAsCString groupName $ \cgroupName ->
+#if (H5Fget_info_vers == 1)
+                h5l_visit_by_name (hid loc) cgroupName (indexTypeCode indexType) (iterOrderCode order) iop opData (maybe h5p_DEFAULT hid lapl)
+#else
+                h5l_visit_by_name2 (hid loc) cgroupName (indexTypeCode indexType) (iterOrderCode order) iop opData (maybe h5p_DEFAULT hid lapl)
+#endif
diff --git a/src/Bindings/HDF5/Raw/H5E.hsc b/src/Bindings/HDF5/Raw/H5E.hsc
--- a/src/Bindings/HDF5/Raw/H5E.hsc
+++ b/src/Bindings/HDF5/Raw/H5E.hsc
@@ -118,7 +118,9 @@
 #cinline H5E_OHDR,              <hid_t>
 
 -- |Object atom
+#if !H5_VERSION_GE(1,8,14)
 #cinline H5E_ATOM,              <hid_t>
+#endif
 
 -- |Attribute
 #cinline H5E_ATTR,              <hid_t>
@@ -284,7 +286,9 @@
 #cinline H5E_MOUNT,             <hid_t>
 
 -- ** Object atom related errors
+#if !H5_VERSION_GE(1,8,14)
 #cinline H5E_BADATOM,           <hid_t>
+#endif
 #cinline H5E_BADGROUP,          <hid_t>
 #cinline H5E_CANTREGISTER,      <hid_t>
 #cinline H5E_CANTINC,           <hid_t>
diff --git a/src/Bindings/HDF5/Raw/H5F.hsc b/src/Bindings/HDF5/Raw/H5F.hsc
--- a/src/Bindings/HDF5/Raw/H5F.hsc
+++ b/src/Bindings/HDF5/Raw/H5F.hsc
@@ -131,44 +131,6 @@
 #newtype_const H5F_close_degree_t, H5F_CLOSE_STRONG
 
 
-#if H5_VERSION_GE(1,10,0)
-
--- |Current "global" information about file
--- (just size info currently)
-#starttype H5F_info2_t
-
--- |Superblock version
-#field super.version,  CUInt
-
--- |Superblock size
-#field super.super_size, <hsize_t>
-
-
--- |Superblock extension size
-#field super.super_ext_size, <hsize_t>
-
--- |Version # of file free space management
-#field free.version, CUInt
-
--- |Free space manager metadata size
-#field free.meta_size, <hsize_t>
-
--- |Amount of free space in the file
-#field free.tot_space, <hsize_t>
-
--- |Version # of shared object header info
-#field sohm.version, CUInt
-
--- |Shared object header message header size
-#field sohm.hdr_size, <hsize_t>
-
--- |Shared object header message index & heap size
-#field sohm.msgs_info, <H5_ih_info_t>
-
-#stoptype
-
-#endif
- 
 #if H5_VERSION_GE(1,8,4)
 
 -- |Types of allocation requests. The values larger than 'h5fd_MEM_DEFAULT'
@@ -573,8 +535,10 @@
 --
 #if H5_VERSION_GE(1,10,0)
 
+#if H5Fget_info_vers == 2
 -- > herr_t H5Fget_info2(hid_t obj_id, H5F_info2_t *bh_info);
-#ccall H5Fget_info2, <hid_t> -> Out H5F_info2_t -> IO <herr_t>
+#ccall H5Fget_info2, <hid_t> -> Out H5F_info_t -> IO <herr_t>
+#endif
 
 -- > herr_t H5Fget_metadata_read_retry_info(hid_t file_id, H5F_retry_info_t *info);
 #ccall H5Fget_metadata_read_retry_info, <hid_t> -> Out H5F_retry_info_t -> IO <herr_t>
@@ -655,7 +619,8 @@
 
 #endif
 
-#if (H5_VERSION_GE(1,10,0) && (H5Fget_info_vers == 1)) || H5_VERSION_LE(1,8,18)
+-- #if (H5_VERSION_GE(1,10,0) && (H5Fget_info_vers == 1)) || H5_VERSION_LE(1,8,18)
+#if H5Fget_info_vers == 1
 
 -- |Current "global" information about file
 -- (just size info currently)
@@ -672,7 +637,7 @@
  
 #stoptype
 
-#else
+#elif H5Fget_info_vers == 2
 
 -- |Current "global" information about file
 -- (just size info currently)
@@ -706,6 +671,12 @@
 #field sohm.msgs_info, <H5_ih_info_t>
 
 #stoptype
+
+type H5F_info2_t = H5F_info_t
+
+#else
+
+#error unknown H5Fget_info_vers
 
 #endif
 
diff --git a/src/Bindings/HDF5/Raw/H5FD.hsc b/src/Bindings/HDF5/Raw/H5FD.hsc
--- a/src/Bindings/HDF5/Raw/H5FD.hsc
+++ b/src/Bindings/HDF5/Raw/H5FD.hsc
@@ -1,5 +1,8 @@
 #include <bindings.h>
 #include <H5FDpublic.h>
+#if H5_VERSION_GE(1,14,0)
+#include <H5FDdevelop.h>
+#endif
 
 -- |The Virtual File Layer as described in documentation.
 -- This is the greatest common denominator for all types of
@@ -350,7 +353,7 @@
 #if H5_VERSION_GE(1,10,0) && H5_VERSION_LE(1,10,1)
 -- |Whether the file is open for SWMR read access
 -- Information from file open flags, for SWMR access
-#field swmr_read, <hbool_t>
+-- #field swmr_read, <hbool_t>
 #endif
 
 -- Space allocation management fields
diff --git a/src/Bindings/HDF5/Raw/H5FD/Direct.hsc b/src/Bindings/HDF5/Raw/H5FD/Direct.hsc
--- a/src/Bindings/HDF5/Raw/H5FD/Direct.hsc
+++ b/src/Bindings/HDF5/Raw/H5FD/Direct.hsc
@@ -7,6 +7,9 @@
 module Bindings.HDF5.Raw.H5FD.Direct where
 
 import Bindings.HDF5.Raw.H5I
+#ifdef H5_HAVE_DIRECT
+import System.IO.Unsafe(unsafePerformIO)
+#endif /* H5_HAVE_DIRECT */
 
 #mangle_ident "H5FD_DIRECT"
   :: HId_t
diff --git a/src/Bindings/HDF5/Raw/H5I.hsc b/src/Bindings/HDF5/Raw/H5I.hsc
--- a/src/Bindings/HDF5/Raw/H5I.hsc
+++ b/src/Bindings/HDF5/Raw/H5I.hsc
@@ -40,9 +40,6 @@
 -- |type ID for Attribute objects
 #newtype_const H5I_type_t, H5I_ATTR
 
--- |type ID for Reference objects
-#newtype_const H5I_type_t, H5I_REFERENCE
-
 -- |type ID for virtual file layer
 #newtype_const H5I_type_t, H5I_VFL
 
diff --git a/src/Bindings/HDF5/Raw/H5L.hsc b/src/Bindings/HDF5/Raw/H5L.hsc
--- a/src/Bindings/HDF5/Raw/H5L.hsc
+++ b/src/Bindings/HDF5/Raw/H5L.hsc
@@ -1,6 +1,9 @@
 #include <bindings.h>
 #include <H5Lpublic.h>
-
+#include <H5version.h>
+#if H5_VERSION_GE(1,14,0)
+#include <H5Ldevelop.h>
+#endif
 module Bindings.HDF5.Raw.H5L where
 
 import Data.Int
@@ -14,6 +17,9 @@
 import Bindings.HDF5.Raw.H5
 import Bindings.HDF5.Raw.H5I
 import Bindings.HDF5.Raw.H5T
+#if H5Fget_info_vers != 1
+import Bindings.HDF5.Raw.H5O
+#endif
 import Foreign.Ptr.Conventions
 
 -- |Maximum length of a link's name
@@ -60,7 +66,13 @@
 #newtype_const H5L_type_t, H5L_TYPE_UD_MIN
 
 -- |Information struct for link (for 'h5l_get_info' / 'h5l_get_info_by_idx')
+#if H5Fget_info_vers == 1
 #starttype H5L_info_t
+#elif H5Fget_info_vers == 2
+#starttype H5L_info2_t
+#else
+#error "unknown info vers"
+#endif
 
 -- |Type of link
 #field type,                <H5L_type_t>
@@ -74,13 +86,22 @@
 -- |Character set of link name
 #field cset,                <H5T_cset_t>
 
+#if (H5Fget_info_vers == 1)
 -- |Address hard link points to
 #union_field u.address,     <haddr_t>
+#else
+#union_field u.token,       <H5O_token_t>
+#endif
 
+
+
 -- |Size of a soft link or UD link value
 #union_field u.val_size,    <size_t>
 #stoptype
 
+#if H5Fget_info_vers == 2
+type H5L_info_t = H5L_info2_t
+#endif
 
 -- /* The H5L_class_t struct can be used to override the behavior of a
 --  * "user-defined" link class. Users should populate the struct with callback
@@ -163,7 +184,11 @@
 --
 -- > typedef herr_t (*H5L_iterate_t)(hid_t group, const char *name, const H5L_info_t *info,
 -- >     void *op_data);
+-- #if (H5Fget_info_vers == 1)
 type H5L_iterate_t a = FunPtr (HId_t -> CString -> In H5L_info_t -> InOut a -> IO HErr_t)
+#if (H5Fget_info_vers != 1)
+type H5L_iterate2_t a = H5L_iterate_t a
+#endif
 
 -- |Callback for external link traversal
 --
diff --git a/src/Bindings/HDF5/Raw/H5O.hsc b/src/Bindings/HDF5/Raw/H5O.hsc
--- a/src/Bindings/HDF5/Raw/H5O.hsc
+++ b/src/Bindings/HDF5/Raw/H5O.hsc
@@ -155,16 +155,37 @@
 
 #endif
 
+#if H5_VERSION_GE(1,11,0)
+
+#starttype H5O_token_t
+
+#field __data,          CUChar
+
+#stoptype
+
+#endif
+
 -- |Information struct for object
 -- (for 'h5o_get_info'/ 'h5o_get_info_by_name' / 'h5o_get_info_by_idx')
+#if (H5Fget_info_vers == 1)
 #starttype H5O_info_t
+#else
+#starttype H5O_info2_t
+#endif
 
 -- |File number that object is located in
 #field fileno,          CULong
 
+#if (H5Fget_info_vers == 1)
 -- |Object address in file
 #field addr,            <haddr_t>
+#endif
 
+-- |Token representing the object
+#if H5_VERSION_GE(1,11,0)
+#field token,            <H5O_token_t>
+#endif
+
 -- |Basic object type (group, dataset, etc.)
 #field type,            <H5O_type_t>
 
@@ -188,11 +209,14 @@
 
 #if H5_VERSION_GE(1,8,4)
 
+#if (H5Fget_info_vers == 1)
 -- |Object header information
 #field hdr,             <H5O_hdr_info_t>
+#endif
 
 #else
 
+#if (H5Fget_info_vers == 1)
 -- |Version number of header format in file
 #field hdr.version,      CUInt
 
@@ -225,20 +249,30 @@
 
 #endif
 
+#endif
+
+#if (H5Fget_info_vers == 1)
 -- |v1/v2 B-tree & local/fractal heap for groups, B-tree for chunked datasets
 #field meta_size.obj,   <H5_ih_info_t>
 
 -- |v2 B-tree & heap for attributes
 #field meta_size.attr,  <H5_ih_info_t>
 
+#endif
+
 #stoptype
 
 
 -- |Typedef for message creation indexes
 #newtype H5O_msg_crt_idx_t, Eq, Ord, Read
 
+#if (H5Fget_info_vers == 1)
 -- |Prototype for 'h5o_visit' / 'h5o_visit_by_name' operator
 type H5O_iterate_t a = FunPtr (HId_t -> CString -> In H5O_info_t -> InOut a -> IO HErr_t)
+#else
+-- |Prototype for 'h5o_visit' / 'h5o_visit_by_name' operator
+type H5O_iterate2_t a = FunPtr (HId_t -> CString -> In H5O_info2_t -> InOut a -> IO HErr_t)
+#endif
 
 #newtype H5O_mcdt_search_ret_t
 
@@ -339,7 +373,11 @@
 -- Returns non-negative on success, negative on failure.
 --
 -- > herr_t H5Oget_info(hid_t loc_id, H5O_info_t *oinfo);
+#if (H5Fget_info_vers == 1)
 #ccall H5Oget_info, <hid_t> -> Out <H5O_info_t> -> IO <herr_t>
+#else
+#ccall H5Oget_info, <hid_t> -> Out <H5O_info2_t> -> IO <herr_t>
+#endif
 
 -- |Retrieve information about an object.
 --
@@ -556,7 +594,11 @@
 --
 -- > herr_t H5Ovisit(hid_t obj_id, H5_index_t idx_type, H5_iter_order_t order,
 -- >     H5O_iterate_t op, void *op_data);
+#if (H5Fget_info_vers == 1)
 #ccall H5Ovisit, <hid_t> -> <H5_index_t> -> <H5_iter_order_t> -> H5O_iterate_t a -> InOut a -> IO <herr_t>
+#else
+#ccall H5Ovisit, <hid_t> -> <H5_index_t> -> <H5_iter_order_t> -> H5O_iterate2_t a -> InOut a -> IO <herr_t>
+#endif
 
 -- |Recursively visit an object and all the objects reachable
 -- from it.  If the starting object is a group, all the objects
diff --git a/src/Bindings/HDF5/Raw/H5S.hsc b/src/Bindings/HDF5/Raw/H5S.hsc
--- a/src/Bindings/HDF5/Raw/H5S.hsc
+++ b/src/Bindings/HDF5/Raw/H5S.hsc
@@ -1,5 +1,6 @@
 #include <bindings.h>
 #include <H5Spublic.h>
+#include <H5version.h>
 
 module Bindings.HDF5.Raw.H5S where
 
@@ -171,7 +172,14 @@
 -- Returns non-negative on success, negative on failure.
 --
 -- > herr_t H5Sencode(hid_t obj_id, void *buf, size_t *nalloc);
+#if HDF5get_info_vers == 1
 #ccall H5Sencode, <hid_t> -> OutArray CChar -> InOut <size_t> -> IO <herr_t>
+#else
+#ccall H5Sencode2, <hid_t> -> OutArray CChar -> InOut <size_t> -> IO <herr_t>
+
+h5s_encode :: HId_t -> OutArray CChar -> InOut CSize -> IO HErr_t
+h5s_encode = h5s_encode2
+#endif
 
 -- |Decode a binary object description of dataspace and
 -- return a new object handle.
diff --git a/src/Bindings/HDF5/Raw/H5T.hsc b/src/Bindings/HDF5/Raw/H5T.hsc
--- a/src/Bindings/HDF5/Raw/H5T.hsc
+++ b/src/Bindings/HDF5/Raw/H5T.hsc
@@ -1,6 +1,9 @@
 #include <bindings.h>
 
 #include <H5Tpublic.h>
+#if H5_VERSION_GE(1,14,0)
+#include <H5Tdevelop.h>
+#endif
 
 module Bindings.HDF5.Raw.H5T where
 
diff --git a/src/Bindings/HDF5/Raw/H5Z.hsc b/src/Bindings/HDF5/Raw/H5Z.hsc
--- a/src/Bindings/HDF5/Raw/H5Z.hsc
+++ b/src/Bindings/HDF5/Raw/H5Z.hsc
@@ -1,6 +1,9 @@
 #include <bindings.h>
 #include <H5Ipublic.h>
 #include <H5Zpublic.h>
+#if H5_VERSION_GE(1,13,0)
+#include <H5Zdevelop.h>
+#endif
 
 module Bindings.HDF5.Raw.H5Z where
 
