|
| 1 | +{-# LANGUAGE CPP #-} |
| 2 | +-- | Compatibility layer for the @unix@ package to provide a @fileSetCaching@ function. |
| 3 | +-- |
| 4 | +-- @unix >= 2.8.7@ defines a @fileSetCaching@ function, but @unix < 2.8.7@ does not. This module defines the function for @unix@ versions @< 2.8.7@. The implementation is adapted from https://github.com/haskell/unix/blob/v2.8.8.0/System/Posix/Fcntl.hsc#L116-L182. |
| 5 | +-- |
| 6 | +-- NOTE: in the future if we no longer support @unix@ versions @< 2.8.7@, then this module can be removed. |
| 7 | +module System.FS.BlockIO.Internal.Fcntl (fileSetCaching) where |
| 8 | + |
| 9 | +#if MIN_VERSION_unix(2,8,7) |
| 10 | + |
| 11 | +import System.Posix.Fcntl (fileSetCaching) |
| 12 | + |
| 13 | +#else |
| 14 | + |
| 15 | +-- hsc2hs does not define _GNU_SOURCE, so a .hsc file must define it explicitly |
| 16 | +-- or O_DIRECT stays hidden. The unix package doesn’t define it in source, but |
| 17 | +-- its configure script calls AC_USE_SYSTEM_EXTENSIONS, which adds -D_GNU_SOURCE |
| 18 | +-- to the build CFLAGS, and those flags are passed on to hsc2hs through the |
| 19 | +-- generated `config.mk`. |
| 20 | +#define _GNU_SOURCE |
| 21 | + |
| 22 | +#include <fcntl.h> |
| 23 | + |
| 24 | +import Data.Bits (complement, (.&.), (.|.)) |
| 25 | +import Foreign.C (throwErrnoIfMinus1, throwErrnoIfMinus1_) |
| 26 | +import System.Posix.Internals |
| 27 | +import System.Posix.Types (Fd (Fd)) |
| 28 | + |
| 29 | +-- | For simplification, we considered that Linux !HAS_F_NOCACHE and HAS_O_DIRECT |
| 30 | +fileSetCaching :: Fd -> Bool -> IO () |
| 31 | +fileSetCaching (Fd fd) val = do |
| 32 | + r <- throwErrnoIfMinus1 "fileSetCaching" (c_fcntl_read fd #{const F_GETFL}) |
| 33 | + let r' | val = fromIntegral r .&. complement opt_val |
| 34 | + | otherwise = fromIntegral r .|. opt_val |
| 35 | + throwErrnoIfMinus1_ "fileSetCaching" (c_fcntl_write fd #{const F_SETFL} r') |
| 36 | + where |
| 37 | + opt_val = #{const O_DIRECT} |
| 38 | +#endif |
0 commit comments