-- return a high level wrapper for a getxattr variant
mkGetxattr :: String -> a -> (a -> IO b) -> (b -> CString -> Ptr Void -> CSize -> IO CSize) -> AttrName -> IO ByteString
mkGetxattr funcName x iox cFunc attrName = do
  x' <- iox x
  cName <- newCString attrName
  allocaBytes allocBufSize $ \mem -> do
    buflen <- cFunc x' cName mem allocCSize
    if buflen == -1
       then throwErrno funcName
       else packCStringLen (mem, fromIntegral buflen)

-- |Get an attribute on a regular file, by path
mkGetxattr :: String -> a -> (a -> IO b) -> (b -> CString -> Ptr Void -> CSize -> IO CSize) -> AttrName -> IO ByteString
mkGetxattr funcName x iox cFunc attrName = do
  x' <- iox x
  cName <- newCString attrName
  allocaBytes allocBufSize $ \mem -> do
    buflen <- cFunc x' cName mem allocCSize
    if buflen == -1
       then throwErrno funcName
       else packCStringLen (mem, fromIntegral buflen)

-- |Get an attribute on a regular file, by path
mkGetxattr funcName x iox cFunc attrName = do
  x' <- iox x
  cName <- newCString attrName
  allocaBytes allocBufSize $ \mem -> do
    buflen <- cFunc x' cName mem allocCSize
    if buflen == -1
       then throwErrno funcName
       else packCStringLen (mem, fromIntegral buflen)

-- |Get an attribute on a regular file, by path