|
16 | 16 | -----------------------------------------------------------------------------
|
17 | 17 |
|
18 | 18 | #include "HsUnix.h"
|
| 19 | +#include <fcntl.h> |
19 | 20 |
|
20 | 21 | module System.Posix.Fcntl (
|
21 | 22 | -- * File allocation
|
22 | 23 | Advice(..), fileAdvise,
|
23 | 24 | fileAllocate,
|
| 25 | + -- * File caching |
| 26 | + fileGetCaching, |
| 27 | + fileSetCaching, |
24 | 28 | ) where
|
25 | 29 |
|
26 |
| -#if HAVE_POSIX_FALLOCATE || HAVE_POSIX_FADVISE |
27 | 30 | import Foreign.C
|
28 |
| -#endif |
29 | 31 | import System.Posix.Types
|
30 | 32 |
|
31 |
| -#if !HAVE_POSIX_FALLOCATE |
| 33 | +#if !HAVE_POSIX_FALLOCATE || !HAVE_O_DIRECT |
32 | 34 | import System.IO.Error ( ioeSetLocation )
|
33 | 35 | import GHC.IO.Exception ( unsupportedOperation )
|
34 | 36 | #endif
|
35 | 37 |
|
| 38 | +#if HAVE_O_DIRECT |
| 39 | +import Data.Bits (complement, (.&.), (.|.)) |
| 40 | +import System.Posix.Internals (c_fcntl_read) |
| 41 | +#endif |
| 42 | + |
| 43 | +#if HAVE_O_DIRECT || HAVE_F_NOCACHE |
| 44 | +import System.Posix.Internals (c_fcntl_write) |
| 45 | +#endif |
| 46 | + |
36 | 47 | -- -----------------------------------------------------------------------------
|
37 | 48 | -- File control
|
38 | 49 |
|
@@ -101,3 +112,71 @@ foreign import capi safe "fcntl.h posix_fallocate"
|
101 | 112 | fileAllocate _ _ _ = ioError (ioeSetLocation unsupportedOperation
|
102 | 113 | "fileAllocate")
|
103 | 114 | #endif
|
| 115 | + |
| 116 | +-- ----------------------------------------------------------------------------- |
| 117 | +-- File caching |
| 118 | + |
| 119 | +-- | Performs the @fcntl(2)@ operation on a file-desciptor to get the cache mode. |
| 120 | +-- |
| 121 | +-- If the cache mode is 'False', then cache effects for file system reads and |
| 122 | +-- writes are minimised or otherwise eliminated. If the cache mode is 'True', |
| 123 | +-- then cache effects occur like normal. |
| 124 | +-- |
| 125 | +-- On Linux, FreeBSD, and NetBSD this checks whether the @O_DIRECT@ file flag is |
| 126 | +-- set. |
| 127 | +-- |
| 128 | +-- Throws 'IOError' (\"unsupported operation\") if platform does not support |
| 129 | +-- getting the cache mode. |
| 130 | +-- |
| 131 | +-- Use @#if HAVE_O_DIRECT@ CPP guard to detect availability. Use @#include |
| 132 | +-- "HsUnix.h"@ to bring @HAVE_O_DIRECT@ into scope. |
| 133 | +-- |
| 134 | +-- @since 2.8.x.y |
| 135 | +fileGetCaching :: Fd -> IO Bool |
| 136 | +#if HAVE_O_DIRECT |
| 137 | +fileGetCaching (Fd fd) = do |
| 138 | + r <- throwErrnoIfMinus1 "fileGetCaching" (c_fcntl_read fd #{const F_GETFL}) |
| 139 | + return ((r .&. opt_val) == 0) |
| 140 | + where |
| 141 | + opt_val = #{const O_DIRECT} |
| 142 | +#else |
| 143 | +{-# WARNING fileGetCaching |
| 144 | + "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_O_DIRECT@)" #-} |
| 145 | +fileGetCaching _ = ioError (ioeSetLocation unsupportedOperation "fileGetCaching") |
| 146 | +#endif |
| 147 | + |
| 148 | +-- | Performs the @fcntl(2)@ operation on a file-desciptor to set the cache |
| 149 | +-- mode. |
| 150 | +-- |
| 151 | +-- If the cache mode is 'False', then cache effects for file system reads and |
| 152 | +-- writes are minimised or otherwise eliminated. If the cache mode is 'True', |
| 153 | +-- then cache effects occur like normal. |
| 154 | +-- |
| 155 | +-- On Linux, FreeBSD, and NetBSD this sets the @O_DIRECT@ file flag. On OSX, |
| 156 | +-- this sets the @F_NOCACHE@ @fcntl@ flag. |
| 157 | +-- |
| 158 | +-- Throws 'IOError' (\"unsupported operation\") if platform does not support |
| 159 | +-- setting the cache mode. |
| 160 | +-- |
| 161 | +-- Use @#if HAVE_O_DIRECT || HAVE_F_NOCACHE@ CPP guard to detect availability. |
| 162 | +-- Use @#include "HsUnix.h"@ to bring @HAVE_O_DIRECT@ and @HAVE_F_NOCACHE@ into |
| 163 | +-- scope. |
| 164 | +-- |
| 165 | +-- @since 2.8.x.y |
| 166 | +fileSetCaching :: Fd -> Bool -> IO () |
| 167 | +#if HAVE_O_DIRECT |
| 168 | +fileSetCaching (Fd fd) val = do |
| 169 | + r <- throwErrnoIfMinus1 "fileSetCaching" (c_fcntl_read fd #{const F_GETFL}) |
| 170 | + let r' | val = fromIntegral r .&. complement opt_val |
| 171 | + | otherwise = fromIntegral r .|. opt_val |
| 172 | + throwErrnoIfMinus1_ "fileSetCaching" (c_fcntl_write fd #{const F_SETFL} r') |
| 173 | + where |
| 174 | + opt_val = #{const O_DIRECT} |
| 175 | +#elif HAVE_F_NOCACHE |
| 176 | +fileSetCaching (Fd fd) val = do |
| 177 | + throwErrnoIfMinus1_ "fileSetCaching" (c_fcntl_write fd #{const F_NOCACHE} (if val then 0 else 1)) |
| 178 | +#else |
| 179 | +{-# WARNING fileSetCaching |
| 180 | + "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_O_DIRECT || HAVE_F_NOCACHE @)" #-} |
| 181 | +fileSetCaching _ _ = ioError (ioeSetLocation unsupportedOperation "fileSetCaching") |
| 182 | +#endif |
0 commit comments