diff --git a/BerkeleyDB.cabal b/BerkeleyDB.cabal
--- a/BerkeleyDB.cabal
+++ b/BerkeleyDB.cabal
@@ -1,5 +1,5 @@
 name:		BerkeleyDB
-version:	0.1
+version:	0.2
 license:	BSD3
 license-file:	LICENSE
 copyright:	John McCall, 2007
@@ -8,7 +8,7 @@
 stability:	alpha
 homepage:	http://www.cs.pdx.edu/~rjmccall/hackage/BerkeleyDB/
 category:	Database
-build-depends:	base
+build-depends:	base, unix
 synopsis:	Bindings for Berkeley DB v1.x
 description:
 	Provides Haskell bindings for Berkeley DB v1.x, a simple file-backed
diff --git a/Database/BerkeleyDB.hsc b/Database/BerkeleyDB.hsc
--- a/Database/BerkeleyDB.hsc
+++ b/Database/BerkeleyDB.hsc
@@ -1,27 +1,19 @@
 {-
-Haskell bindings for Berkeley DB v1.5, i.e. <db.h> on BSD-derived Unices.
-This module is intended to be imported qualified.
-
-The database implementations provided by this module are not safe
-against concurrent access;  for that, users must seek a more resilient
-database.
-
-This module has been written with GHC 6.6 in mind; it is quite
-possible that it will function with minimal changes on other
-implementations of Haskell or earlier versions of GHC, and patches for
-this purpose would be welcome, providing they don't compromise the integrity
-of the up-to-date GHC implementation.
+  Database.BerkeleyDB v0.2
+  Copyright 2007 John McCall
+  Licensed for general use under a BSD3-style license;  for the exact
+  license text, see the LICENSE file included in this distribution.  If
+  you find this file distributed without a LICENSE file, please contact
+  me at rjmccall@gmail.com and tell me where you found it.
 
-The open functions generally interpret IO mode as follows:
- - ReadMode attempts to open a database in read-only mode;  if the database
-   doesn't exist, an exception is thrown.
- - ReadWriteMode and AppendMode are synonymous;  both open the database in
-   read/write mode, creating it if necessary.
- - WriteMode opens the database in read/write mode, but it truncates any
-   existing database file.
+  It's my hope that this module could be used to bootstrap bindings for a
+  modern version of Berkeley DB, but I'm not currently working on that.
 
-This file could also be used to bootstrap bindings for a modern version of
-Berkeley DB.
+  Author:      John McCall <rjmccall@gmail.com>
+  Maintainer:  John McCall <rjmccall@gmail.com>
+  History:
+     v0.2   2007-04-06      Haddock documentation; FileMode.
+     v0.1   2007-04-05      Creation.
 -}
 
 {- We require a preprocessor pass in order to bring the structure
@@ -42,6 +34,31 @@
 #let alignment type = "alignment (undefined :: Ptr a)"
 #endif
 
+{-|
+Haskell bindings for Berkeley DB v1.85, i.e. @db.h@ on BSD-derived Unices.
+This module is intended to be imported qualified.
+
+The database implementations provided by this module are not safe
+against concurrent access;  for that, users must seek a more resilient
+database.
+
+This module has been written with GHC 6.6 in mind; it is quite
+possible that it will function with minimal changes on other
+implementations of Haskell or earlier versions of GHC, and patches for
+this purpose would be welcome, providing they don't compromise the integrity
+of the up-to-date GHC implementation.
+
+The open functions generally interpret 'IOMode' as follows:
+
+- 'ReadMode' attempts to open a database in read-only mode;  if the database
+   doesn't exist, an exception is thrown.
+
+- 'ReadWriteMode' and 'AppendMode' are synonymous;  both open the database in
+   read\/write mode, creating it if necessary.
+
+- 'WriteMode' opens the database in read\/write mode, but it truncates any
+   existing database file.
+ -}
 module Database.BerkeleyDB
     (HashDB, openHash, HashDBCursor,HashDBConf(..), defaultHashDBConf,
      TreeDB, openTree, TreeDBCursor,TreeDBConf(..), defaultTreeDBConf, 
@@ -49,9 +66,13 @@
        RecordDBConf(..), defaultRecordDBConf,
      FixedRecordDB, openFixedRecord, FixedRecordDBCursor,
        FixedRecordDBConf(..), defaultFixedRecordDBConf,
-     DB(..), DBCursor(..), IOMode(..), UMask) where
+     DB(..), DBCursor(..),
+     IOMode(..)) where
 
-import System.IO
+import System.IO (IOMode(..))  -- re-exported
+import System.Posix.Files      -- for FileMode's helpful constants
+import System.Posix.Types      -- for mode_t
+
 import Foreign
 import Foreign.C
 import Control.Monad (when, liftM)
@@ -59,30 +80,27 @@
 import Data.ByteString (ByteString, packCStringLen, copyCStringLen, useAsCStringLen)
 import Prelude hiding (lookup)
 
------- ELEMENTARY DEFINITIONS -------
-
-{- POSIX file-creation masks;  see the manpage for umask(2). -}
-
-type UMask = Int
-
-{- The default umask doesn't restrict created files in any way other than
-   that specified in the process umask. -}
-
-defaultUmask :: UMask
-defaultUmask = 0666
+{- We use 0666 as our default umask, but we define it in this crazy way. -}
+defaultUmask :: FileMode
+defaultUmask = foldl1 unionFileModes [ownerReadMode,
+                                      ownerWriteMode,
+                                      groupReadMode,
+                                      groupWriteMode,
+                                      otherReadMode,
+                                      otherWriteMode]
 
 --------- TYPE CLASSES ---------
 
-{- Common operations supported by databases.  The database type
-   functionally defines its key, value, and cursor types. -}
+{-| Common operations supported by databases.  The database type
+    functionally defines its key, value, and cursor types. -}
 class (DBCursor c k v) => DB t c k v | t -> c k v where
 
-   {- The simplified "open" command.  Individual database types usually
+  {-| The simplified "open" command.  Individual database types usually
       provide a specialized open operation.  If no filepath is given, the
       database will exist primarily in memory or a temporary file. -}
   open   :: Maybe FilePath -> IOMode -> IO t
 
-   {- Closes the database.  Just as with files, it's important to explicitly
+  {-| Closes the database.  Just as with files, it's important to explicitly
       close a database to avoid memory leaks;  it's also important to explicitly
       close a database in order to flush database writes which might currently
       be cached.
@@ -92,66 +110,66 @@
       database object after it's been closed. -}
   close  :: t -> IO ()
 
-  {- Inserts an entry into the database. -}
+  {-| Inserts an entry into the database. -}
   insert :: t -> k -> v -> IO ()
 
-  {- Looks up an entry in the database. -}
+  {-| Looks up an entry in the database. -}
   lookup :: t -> k -> IO (Maybe v)
 
-  {- Deletes an entry from the database.  Returns true if the entry existed
-     before it was deleted. -}
+  {-| Deletes an entry from the database.  Returns true if the entry existed
+      before it was deleted. -}
   delete :: t -> k -> IO Bool
 
-  {- Creates a new cursor for sequential access to the database.  The
-     standard Berkeley DB implementations only support a single cursor
-     per database, so even if multiple cursors are created, they'll
-     all change the same state.  Other database implementations might
-     support multiple simultaneous cursors. -}
+  {-| Creates a new cursor for sequential access to the database.  The
+      standard Berkeley DB implementations only support a single cursor
+      per database, so even if multiple cursors are created, they'll
+      all change the same state.  Other database implementations might
+      support multiple simultaneous cursors. -}
   cursor :: t -> IO c
 
-  {- Forces a sync with the disk, to the extent that this is possible
-     with system calls. -}
+  {-| Forces a sync with the disk, to the extent that this is possible
+      with system calls. -}
   sync   :: t -> IO ()
 
 
-{- A type-class for database cursors.  The cursor type functionally
-   defines the key and value types. -}
+{-| A type-class for database cursors.  The cursor type functionally
+    defines the key and value types. -}
 class DBCursor c k v | c -> k v where
 
-  {- Jumps to the first entry in the database. -}
+  {-| Jumps to the first entry in the database. -}
   jumpFirst  :: c -> IO (Maybe (k,v))
 
-  {- Jumps to the last entry in the database.  Not all database
-     implementations support this operation. -}
+  {-| Jumps to the last entry in the database.  Not all database
+      implementations support this operation. -}
   jumpLast   :: c -> IO (Maybe (k,v))
 
-  {- Jumps to an arbitrary place in the database.  The returned match
-     may not be an exact match for the key;  see the notes for each
-     database implementation for more details. -}
+  {-| Jumps to an arbitrary place in the database.  The returned match
+      may not be an exact match for the key;  see the notes for each
+      database implementation for more details. -}
   jump       :: c -> k -> IO (Maybe (k,v))
 
-  {- Moves to the next entry in the database. -}
+  {-| Moves to the next entry in the database. -}
   next       :: c -> IO (Maybe (k,v))
 
-  {- Moves to the previous entry in the database. -}
+  {-| Moves to the previous entry in the database. -}
   previous   :: c -> IO (Maybe (k,v))
 
-  {- Replaces the current entry with a new value.  The cursor must be
-     initialized for this operation to succeed. -}
+  {-| Replaces the current entry with a new value.  The cursor must be
+      initialized for this operation to succeed. -}
   replace    :: c -> k -> v -> IO ()
 
-  {- Removes the entry at the current cursor position. -}
+  {-| Removes the entry at the current cursor position. -}
   remove     :: c -> IO ()
 
-  {- Closes the cursor.  For Berkeley databases, this doesn't do anything. -}
+  {-| Closes the cursor.  For Berkeley databases, this doesn't do anything. -}
   closeCursor:: c -> IO ()
 
 
 -------- GENERAL IMPLEMENTATION -------
 
 {- The type of databases;  in C-land, this is "DB".  Here, it's
-   completely opaque, we never try to modify it, and we don't export
-   it. -}
+    completely opaque, we never try to modify it, and we don't export
+    it. -}
 data DBStruct = DBStruct
 
 {- The type of "database thangs";  in C-land, this is "DBT". -}
@@ -241,7 +259,7 @@
 
 ------- HASHTABLES --------
 
-{- Hashtable-based databases. -}
+{-| Hashtable-based databases. -}
 data HashDB = HashDB (Ptr DBStruct) Bool HashToken
 instance DB HashDB HashDBCursor ByteString ByteString where
   open file mode = openHash file mode defaultUmask defaultHashDBConf
@@ -254,7 +272,7 @@
   cursor (HashDB ptr sf _)     = liftM HashDBCursor $ newCursor ptr sf
   sync   (HashDB ptr sf _)     = _sync ptr
 
-{- The type of hashtable database cursors. -}
+{-| The type of hashtable database cursors. -}
 newtype HashDBCursor = HashDBCursor Cursor
 instance DBCursor HashDBCursor ByteString ByteString where
   jump (HashDBCursor c)        = jump c
@@ -266,39 +284,40 @@
   remove (HashDBCursor c)      = remove c
   closeCursor (HashDBCursor c) = closeCursor c
 
-{- The configuration of a hashtable database. -}
+{-| The configuration of a hashtable database. -}
 data HashDBConf = HashDBConf {
 
-  {- The size of a hash bucket, in bytes. -}
+  {-| The size of a hash bucket, in bytes. -}
   hash_bucketSize :: Int,
 
-  {- A desired density for the hashtable.  This value approximates the
-     maximum number of keys allowed in a bucket;  the default value is 8. -}
+  {-| A desired density for the hashtable.  This value approximates the
+      maximum number of keys allowed in a bucket;  the default value is 8. -}
   hash_keyDensity :: Int,
 
-  {- The initial size of the database.  The hashtable will grow gracefully 
-     as keys are added, but performance may temporarily suffer at each
-     expansion, so it's always better to get this right. -}
+  {-| The initial size of the database.  The hashtable will grow gracefully 
+      as keys are added, but performance may temporarily suffer at each
+      expansion, so it's always better to get this right. -}
   hash_initialSize :: Int,
 
-  {- An advistory maximum size for the in-memory database cache. -}
+  {-| An advistory maximum size for the in-memory database cache. -}
   hash_cacheSize :: Int,
 
-  {- The byte order of hashtable metadata;  for example, 4321 specifies a
-     big-endian format.  Not all byte orders are necessarily supported, and
-     this setting is ignored when opening existing databases.  0 means to use
-     host order. -}
+  {-| The byte order of hashtable metadata;  for example, 4321 specifies a
+      big-endian format.  Not all byte orders are necessarily supported, and
+      this setting is ignored when opening existing databases.  0 means to use
+      host order. -}
   hash_byteOrder :: Int,
 
-  {- A custom hash function.  Specifying a custom hash function can
-     sometimes improve hashtable performance, depending on the expected
-     range of keys; however, since it requires a callback into Haskell, it
-     can also hurt performance by requiring "safe" calls into C (which forces
-     the runtime system to stabilize itself before every database call). -}
+  {-| A custom hash function.  Specifying a custom hash function can
+      sometimes improve hashtable performance, depending on the expected
+      range of keys; however, since it requires a callback into Haskell, it
+      can also hurt performance by requiring "safe" calls into C (which forces
+      the runtime system to stabilize itself before every database call). -}
   hash_hashFunction :: Maybe (ByteString -> Word32)
 }
 
-{- The default database configuration. -}
+{-| The default database configuration. -}
+defaultHashDBConf :: HashDBConf
 defaultHashDBConf = HashDBConf {
   hash_bucketSize = 0,
   hash_keyDensity = 0,
@@ -308,15 +327,15 @@
   hash_hashFunction = Nothing
 }
 
-{- Opens or creates a hashtable database. -}
-openHash :: Maybe FilePath -> IOMode -> UMask -> HashDBConf -> IO HashDB
+{-| Opens or creates a hashtable database. -}
+openHash :: Maybe FilePath -> IOMode -> FileMode -> HashDBConf -> IO HashDB
 openHash path iomode umask conf = 
   withMaybeString path $ \cpath ->
   alloca $ \info ->
   allocFunPtr (makeHash $ hash_hashFunction conf) $ \fpHash -> do
     writeHashDBConf conf fpHash info
     ptr <- throwErrnoIfNull "BerkeleyDB.openHash"
-      $ db_open_hash cpath (fromIOMode iomode) (toEnum umask) info
+      $ db_open_hash cpath (fromIOMode iomode) umask info
     let safe = fpHash /= nullFunPtr
     return $ HashDB ptr safe fpHash
 
@@ -389,7 +408,7 @@
 
 ------- B-TREE DATABASES ---------
 
-{- A database built on a b-tree. -}
+{-| A database built on a b-tree. -}
 data TreeDB = TreeDB (Ptr DBStruct) Bool TreeToken
 instance DB TreeDB TreeDBCursor ByteString ByteString where
   open file mode = openTree file mode defaultUmask defaultTreeDBConf
@@ -402,7 +421,7 @@
   sync   (TreeDB ptr sf _)     = _sync ptr
   cursor (TreeDB ptr sf _)     = liftM TreeDBCursor (newCursor ptr sf)
 
-{- The cursor for a tree database. -}
+{-| The cursor for a tree database. -}
 newtype TreeDBCursor = TreeDBCursor Cursor
 instance DBCursor TreeDBCursor ByteString ByteString where
   jump (TreeDBCursor c)        = jump c
@@ -414,51 +433,52 @@
   remove (TreeDBCursor c)      = remove c
   closeCursor (TreeDBCursor c) = closeCursor c
 
-{- The configuration for a b-tree database. -}
+{-| The configuration for a b-tree database. -}
 data TreeDBConf = TreeDBConf {
 
-  {- Permit multiple entries to appear in the database per key.  Only
-     sequential operations can observe the difference. -}
+  {-| Permit multiple entries to appear in the database per key.  Only
+      sequential operations can observe the difference. -}
   tree_duplicateKeys  :: Bool,
 
-  {- An advistory maximum size of the in-memory database cache, in
-     bytes.  A default cache size is used if this value is 0. -}
+  {-| An advistory maximum size of the in-memory database cache, in
+      bytes.  A default cache size is used if this value is 0. -}
   tree_cacheSize      :: Int,
 
-  {- An advisory maximum number of keys to store on a page.  btree(3)
-     says this isn't implemented. -}
+  {-| An advisory maximum number of keys to store on a page.  btree(3)
+      says this isn't implemented. -}
   tree_maxKeysPerPage :: Int,
 
-  {- The minimum number of keys to store on a page (other than the
-     root).  This can never been less than 2. -}
+  {-| The minimum number of keys to store on a page (other than the
+      root).  This can never been less than 2. -}
   tree_minKeysPerPage :: Int,
 
-  {- The size of each pages of the btree, in bytes.  This much be at
-     least 512 and no more than 64K; if it is zero, a default size is
-     chosen based on the filesystem block size.  This value is ignored
-     when opening existing databases. -}
+  {-| The size of each pages of the btree, in bytes.  This much be at
+      least 512 and no more than 64K; if it is zero, a default size is
+      chosen based on the filesystem block size.  This value is ignored
+      when opening existing databases. -}
   tree_pageSize       :: Int,
 
-  {- The byte order of btree metadata;  for example, 4321 specifies a
-     big-endian format.  Not all byte orders are necessarily supported,
-     and this setting is ignored when opening existing databases.  0 means
-     to use host order. -}
+  {-| The byte order of btree metadata;  for example, 4321 specifies a
+      big-endian format.  Not all byte orders are necessarily supported,
+      and this setting is ignored when opening existing databases.  0 means
+      to use host order. -}
   tree_byteOrder      :: Int,
 
-  {- A comparison function for keys.  It is important that the same function
-     be used every time the tree is opened.  The default comparison order is
-     lexicographic (i.e. shorter keys sort first, then each byte is compared
-     from the beginning to the end). -}
+  {-| A comparison function for keys.  It is important that the same function
+      be used every time the tree is opened.  The default comparison order is
+      lexicographic (i.e. shorter keys sort first, then each byte is compared
+      from the beginning to the end). -}
   tree_compare        :: Maybe (ByteString -> ByteString -> Ordering),
 
-  {- A function indicating how many bytes are required from the second key
-     argument in order to decide the ordering.  If the keys are equal, this
-     should be the length of the key.  This can produce highly-compressed trees
-     in certain domains. -}
+  {-| A function indicating how many bytes are required from the second key
+      argument in order to decide the ordering.  If the keys are equal, this
+      should be the length of the key.  This can produce highly-compressed trees
+      in certain domains. -}
   tree_prefix         :: Maybe (ByteString -> ByteString -> Int)
 }
 
-{- The default b-tree configuration. -}
+{-| The default b-tree configuration. -}
+defaultTreeDBConf :: TreeDBConf
 defaultTreeDBConf = TreeDBConf {
   tree_duplicateKeys = False, -- disallow duplicate keys
   tree_cacheSize = 0,         -- use default cache size
@@ -470,17 +490,17 @@
   tree_byteOrder = 0          -- host order
 }
 
-{- Opens a b-tree database, failing with an I/O exception if the database
-   couldn't be opened. -}
-openTree :: Maybe FilePath -> IOMode -> UMask -> TreeDBConf -> IO TreeDB
-openTree path iomode umask conf =
+{-| Opens a b-tree database, failing with an I\/O exception if the database
+    couldn't be opened. -}
+openTree :: Maybe FilePath -> IOMode -> FileMode -> TreeDBConf -> IO TreeDB
+openTree path iomode filemode conf =
   alloca $ \info ->
   withMaybeString path $ \cpath ->
   allocFunPtr (makeCompare $ tree_compare conf) $ \fpCompare ->
   allocFunPtr (makePrefix $ tree_prefix conf) $ \fpPrefix -> do
     writeTreeDBConf conf fpCompare fpPrefix info
     ptr <- throwErrnoIfNull "BerkeleyDB.openTree"
-      $ db_open_btree cpath (fromIOMode iomode) (toEnum umask) info
+      $ db_open_btree cpath (fromIOMode iomode) filemode info
     let safe = fpCompare /= nullFunPtr || fpPrefix /= nullFunPtr
     return $ TreeDB ptr safe (fpCompare,fpPrefix)
 
@@ -577,9 +597,9 @@
 
 ------- RECORD DATABASES --------
 
-{- recno_t, the type of record indices.  recno(3) says this is "normally
-   the largest unsigned integral type available to the implementation", but on
-   modern systems it's usually just uint32_t. -}
+{-| recno_t, the type of record indices.  recno(3) says this is "normally
+    the largest unsigned integral type available to the implementation", but on
+    modern systems it's usually just uint32_t. -}
 newtype Record = Record Recno
   deriving (Bits,Bounded,Enum,Eq,Integral,Num,
             Ord,Read,Real,Show,Storable)
@@ -587,6 +607,12 @@
 
 {- The type of record cursors. -}
 newtype RecCursor = RecCursor (Ptr DBStruct)
+
+-- Haddock wants to publicize this because it mentions Record, but I
+-- don't really want to preprocess before running Haddock, because CPP
+-- will throw all the HSC stuff in my face.  Really, Haddock needs to
+-- recognize that this instance is functionally defined by a private
+-- type and therefore not expose it.
 instance DBCursor RecCursor Record ByteString where
   jump      (RecCursor ptr) (Record key) = _cursorRecord ptr key #{const R_CURSOR}
   jumpFirst (RecCursor ptr) = _cursorRecord ptr 0 #{const R_FIRST}
@@ -596,10 +622,11 @@
   replace   (RecCursor ptr) (Record key) val = _insertRecord ptr key val #{const R_SETCURSOR}
   remove    (RecCursor ptr) = _deleteCursor False ptr -- never needs to be safe
   closeCursor _             = return ()
+
 newRecCursor :: Ptr DBStruct -> IO RecCursor
 newRecCursor ptr = return $ RecCursor ptr
 
-{- Variable-length record databases. -}
+{-| Variable-length record databases. -}
 newtype RecordDB = RecordDB (Ptr DBStruct)
 instance DB RecordDB RecordDBCursor Record ByteString where
   open file mode = openRecord file mode defaultUmask defaultRecordDBConf
@@ -610,8 +637,8 @@
   cursor (RecordDB ptr)     = liftM RecordDBCursor $ newRecCursor ptr
   sync   (RecordDB ptr)     = _sync ptr
 
-{- The type of variable-length record database cursors.  The key returned by
-   cursor procedures is always 0. -}
+{-| The type of variable-length record database cursors.  The key returned by
+    cursor procedures is always 0. -}
 newtype RecordDBCursor = RecordDBCursor RecCursor
 instance DBCursor RecordDBCursor Record ByteString where
   jump (RecordDBCursor c)        = jump c
@@ -623,34 +650,56 @@
   remove (RecordDBCursor c)      = remove c
   closeCursor (RecordDBCursor c) = closeCursor c
 
-{- A configuration for variable-length record databases. -}
+{-| A configuration for variable-length record databases. -}
 data RecordDBConf = RecordDBConf {
---  record_noKey         :: Bool,
+  {-| Forces a snapshot of the database to be taken when the file
+      is opened. -}
   record_snapshot      :: Bool,
+
+  {-| An advisory maximum size of the in-memory database cache. -}
   record_cacheSize     :: Int,
+
+  {-| The page size used for the in-memory database cache, which happens
+      to be a b-tree.  If this value is 0, a default size will be chosen. -}
   record_pageSize      :: Int,
+
+  {-| The byte order for integers in the database metadata;  for example,
+      4321 represents big-endian order.  Not all orders are guaranteed to
+      be supported;  if the byte order is 0, host order will be used.
+      Unlike the other database types, record databases have no metadata,
+      so it's important to get this right when opening existing
+      databases. -}
   record_byteOrder     :: Int,
+
+  {-| The byte value used to separate records in the database.  By default,
+      this is a newline character (0x0A). -}
   record_separatorByte :: Word8,
+
+  {-| A file which should be used to store the the in-memory record cache. -}
   record_treeFile      :: Maybe String
 }
+
+{-| The default variable-length record database configuration. -}
+defaultRecordDBConf :: RecordDBConf
 defaultRecordDBConf = RecordDBConf {
 --  record_noKey         = False,
   record_snapshot      = False,
   record_cacheSize     = 0,
   record_pageSize      = 0,
   record_byteOrder     = 0,
-  record_separatorByte = 32,   -- ' '
+  record_separatorByte = 0x0a,
   record_treeFile      = Nothing
 }
 
-openRecord :: Maybe FilePath -> IOMode -> UMask -> RecordDBConf -> IO RecordDB
-openRecord path iomode umask conf =
+{-| Opens a variable-length record database. -}
+openRecord :: Maybe FilePath -> IOMode -> FileMode -> RecordDBConf -> IO RecordDB
+openRecord path iomode filemode conf =
   withMaybeString path $ \cpath ->
   withMaybeString (record_treeFile conf) $ \ctreefile ->
   alloca $ \info -> do
     writeRecordDBConf conf ctreefile info
     ptr <- throwErrnoIfNull "BerkeleyDB.openRecord"
-      $ db_open_recno cpath (fromIOMode iomode) (toEnum umask) info
+      $ db_open_recno cpath (fromIOMode iomode) filemode info
     return $ RecordDB ptr
 
 {- Writes a variable-length record database configuration into a C structure.
@@ -670,7 +719,7 @@
     ri_bfname    = bfname
   }
 
-{- Fixed-length record databases. -}
+{-| Fixed-length record databases. -}
 newtype FixedRecordDB = FixedRecordDB (Ptr DBStruct)
 instance DB FixedRecordDB FixedRecordDBCursor Record ByteString where
   open file mode = openFixedRecord file mode defaultUmask defaultFixedRecordDBConf
@@ -681,8 +730,8 @@
   cursor (FixedRecordDB ptr)     = liftM FixedRecordDBCursor $ newRecCursor ptr
   sync   (FixedRecordDB ptr)     = _sync ptr
 
-{- The type of fixed-length record database cursors.  The key returned by
-   cursor procedures is always 0. -}
+{-| The type of fixed-length record database cursors.  The key returned by
+    cursor procedures is always 0. -}
 newtype FixedRecordDBCursor = FixedRecordDBCursor RecCursor
 instance DBCursor FixedRecordDBCursor Record ByteString where
   jump (FixedRecordDBCursor c)        = jump c
@@ -694,37 +743,61 @@
   remove (FixedRecordDBCursor c)      = remove c
   closeCursor (FixedRecordDBCursor c) = closeCursor c
 
-{- A configuration for fixed-length record databases. -}
+{-| A configuration for fixed-length record databases. -}
 data FixedRecordDBConf = FixedRecordDBConf {
---  fixed_noKey        :: Bool,
+  {-| Forces a snapshot of the database to be taken when the file
+      is opened. -}
   fixed_snapshot     :: Bool,
+
+  {-| An advisory maximum size of the in-memory database cache. -}
   fixed_cacheSize    :: Int,
+
+  {-| The page size used for the in-memory database cache, which happens
+      to be a b-tree.  If this value is 0, a default size will be chosen. -}
   fixed_pageSize     :: Int,
+
+  {-| The fixed length of the records.  This must be manually overridden in
+      the default configuration, or an exception will be thrown. -}
   fixed_recordLength :: Int,
+
+  {-| The byte order for integers in the database metadata;  for example,
+      4321 represents big-endian order.  Not all orders are guaranteed to
+      be supported;  if the byte order is 0, host order will be used.
+      Unlike the other database types, record databases have no metadata,
+      so it's important to get this right when opening existing
+      databases. -}
   fixed_byteOrder    :: Int,
+
+  {-| The byte value used to pad fixed-length records in the database.
+      By default, this is a space character (0x20). -}
   fixed_paddingByte  :: Word8,
+
+  {-| A file which should be used to store the the in-memory record cache. -}
   fixed_treeFile     :: Maybe String
 }
+
+{-| The default configuration for fixed-length record databases. -}
+defaultFixedRecordDBConf :: FixedRecordDBConf
 defaultFixedRecordDBConf = FixedRecordDBConf {
---  fixed_noKey        = False,
   fixed_snapshot     = False,
   fixed_cacheSize    = 0,
   fixed_pageSize     = 0,
   fixed_recordLength = 0,
   fixed_byteOrder    = 0,
-  fixed_paddingByte  = 10, -- '\n'
+  fixed_paddingByte  = 0x20,
   fixed_treeFile     = Nothing
 }
 
-{- Opens or creates a fixed-length record database. -}
-openFixedRecord :: Maybe FilePath -> IOMode -> UMask -> FixedRecordDBConf -> IO FixedRecordDB
-openFixedRecord path iomode umask conf =
+{-| Opens or creates a fixed-length record database. -}
+openFixedRecord :: Maybe FilePath -> IOMode -> FileMode -> FixedRecordDBConf -> IO FixedRecordDB
+openFixedRecord path iomode filemode conf =
+  if (fixed_recordLength conf <= 0) then fail "non-positive record length" else
   withMaybeString path $ \cpath ->
   withMaybeString (fixed_treeFile conf) $ \ctreefile ->
   alloca $ \info -> do
     writeFixedRecordDBConf conf ctreefile info
     ptr <- throwErrnoIfNull "BerkeleyDB.openFixedRecord"
-      $ db_open_recno cpath (fromIOMode iomode) (toEnum umask) info
+      $ db_open_recno cpath (fromIOMode iomode) filemode info
     return $ FixedRecordDB ptr
 
 {- Writes a fixed record database configuration into a C structure.
@@ -898,25 +971,25 @@
 {- Creation calls are all unsafe. -}
 
 foreign import ccall unsafe "db_open_recno"
-  db_open_recno :: CString -> CInt -> CInt -> Ptr RECNOINFO -> IO (Ptr DBStruct)
+  db_open_recno :: CString -> CInt -> CMode -> Ptr RECNOINFO -> IO (Ptr DBStruct)
 #{def
-  DB *db_open_recno(const char *path, int flags, int umask, RECNOINFO *info) {
+  DB *db_open_recno(const char *path, int flags, mode_t umask, RECNOINFO *info) {
     return dbopen(path, flags, umask, DB_RECNO, info);
   }
 }
 
 foreign import ccall unsafe "db_open_hash"
-  db_open_hash  :: CString -> CInt -> CInt -> Ptr HASHINFO -> IO (Ptr DBStruct)
+  db_open_hash  :: CString -> CInt -> CMode -> Ptr HASHINFO -> IO (Ptr DBStruct)
 #{def
-  DB *db_open_hash(const char *path, int flags, int umask, HASHINFO *info) {
+  DB *db_open_hash(const char *path, int flags, mode_t umask, HASHINFO *info) {
     return dbopen(path, flags, umask, DB_HASH, info);
   }
 }
 
 foreign import ccall unsafe "db_open_btree"
-  db_open_btree :: CString -> CInt -> CInt -> Ptr BTREEINFO -> IO (Ptr DBStruct)
+  db_open_btree :: CString -> CInt -> CMode -> Ptr BTREEINFO -> IO (Ptr DBStruct)
 #{def
-  DB *db_open_btree(const char *path, int flags, int umask, BTREEINFO *info) {
+  DB *db_open_btree(const char *path, int flags, mode_t umask, BTREEINFO *info) {
     return dbopen(path, flags, umask, DB_BTREE, info);
   }
 }
