aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Marios Titas <redneb@gmx.com>2012-06-13 02:52:03 -0400
committerGravatar Paolo Capriotti <p.capriotti@gmail.com>2012-07-17 16:42:13 +0100
commit9acb33c819356a49068ec041c38e438d335e9781 (patch)
tree470f4104a42dd64f2763aed6d34cea1d5611136c
parentba7961f118f42ba9db7e5fba017270a257852ff3 (diff)
Extract high resolution timestamps from FileStatus
Signed-off-by: Paolo Capriotti <p.capriotti@gmail.com>
-rw-r--r--System/Posix/Files.hsc1
-rw-r--r--System/Posix/Files/ByteString.hsc1
-rw-r--r--System/Posix/Files/Common.hsc78
-rw-r--r--configure.ac16
-rw-r--r--tests/fileStatus.hs5
-rw-r--r--tests/fileStatusByteString.hs5
-rw-r--r--unix.cabal3
7 files changed, 106 insertions, 3 deletions
diff --git a/System/Posix/Files.hsc b/System/Posix/Files.hsc
index 5916d1a..cb9663c 100644
--- a/System/Posix/Files.hsc
+++ b/System/Posix/Files.hsc
@@ -57,6 +57,7 @@ module System.Posix.Files (
deviceID, fileID, fileMode, linkCount, fileOwner, fileGroup,
specialDeviceID, fileSize, accessTime, modificationTime,
statusChangeTime,
+ accessTimeHiRes, modificationTimeHiRes, statusChangeTimeHiRes,
isBlockDevice, isCharacterDevice, isNamedPipe, isRegularFile,
isDirectory, isSymbolicLink, isSocket,
diff --git a/System/Posix/Files/ByteString.hsc b/System/Posix/Files/ByteString.hsc
index 5853ab9..cb183ff 100644
--- a/System/Posix/Files/ByteString.hsc
+++ b/System/Posix/Files/ByteString.hsc
@@ -55,6 +55,7 @@ module System.Posix.Files.ByteString (
deviceID, fileID, fileMode, linkCount, fileOwner, fileGroup,
specialDeviceID, fileSize, accessTime, modificationTime,
statusChangeTime,
+ accessTimeHiRes, modificationTimeHiRes, statusChangeTimeHiRes,
isBlockDevice, isCharacterDevice, isNamedPipe, isRegularFile,
isDirectory, isSymbolicLink, isSocket,
diff --git a/System/Posix/Files/Common.hsc b/System/Posix/Files/Common.hsc
index 2894244..01f9fb3 100644
--- a/System/Posix/Files/Common.hsc
+++ b/System/Posix/Files/Common.hsc
@@ -54,6 +54,7 @@ module System.Posix.Files.Common (
deviceID, fileID, fileMode, linkCount, fileOwner, fileGroup,
specialDeviceID, fileSize, accessTime, modificationTime,
statusChangeTime,
+ accessTimeHiRes, modificationTimeHiRes, statusChangeTimeHiRes,
isBlockDevice, isCharacterDevice, isNamedPipe, isRegularFile,
isDirectory, isSymbolicLink, isSocket,
@@ -71,6 +72,8 @@ import System.Posix.Error
import System.Posix.Types
import System.IO.Unsafe
import Data.Bits
+import Data.Time.Clock.POSIX
+import Data.Ratio
import System.Posix.Internals
import Foreign hiding (unsafePerformIO)
import Foreign.C
@@ -233,10 +236,16 @@ specialDeviceID :: FileStatus -> DeviceID
fileSize :: FileStatus -> FileOffset
-- | Time of last access.
accessTime :: FileStatus -> EpochTime
+-- | Time of last access in sub-second resolution.
+accessTimeHiRes :: FileStatus -> POSIXTime
-- | Time of last modification.
modificationTime :: FileStatus -> EpochTime
+-- | Time of last modification in sub-second resolution.
+modificationTimeHiRes :: FileStatus -> POSIXTime
-- | Time of last status change (i.e. owner, group, link count, mode, etc.).
statusChangeTime :: FileStatus -> EpochTime
+-- | Time of last status change (i.e. owner, group, link count, mode, etc.) in sub-second resolution.
+statusChangeTimeHiRes :: FileStatus -> POSIXTime
deviceID (FileStatus stat) =
unsafePerformIO $ withForeignPtr stat $ (#peek struct stat, st_dev)
@@ -261,6 +270,75 @@ modificationTime (FileStatus stat) =
statusChangeTime (FileStatus stat) =
unsafePerformIO $ withForeignPtr stat $ (#peek struct stat, st_ctime)
+accessTimeHiRes (FileStatus stat) =
+ unsafePerformIO $ withForeignPtr stat $ \stat -> do
+ sec <- (#peek struct stat, st_atime) stat :: IO EpochTime
+#ifdef HAVE_STRUCT_STAT_ST_ATIM
+ nsec <- (#peek struct stat, st_atim.tv_nsec) stat :: IO (#type long)
+ let frac = toInteger nsec % 10^9
+#elif HAVE_STRUCT_STAT_ST_ATIMESPEC
+ nsec <- (#peek struct stat, st_atimespec.tv_nsec) stat :: IO (#type long)
+ let frac = toInteger nsec % 10^9
+#elif HAVE_STRUCT_STAT_ST_ATIMENSEC
+ nsec <- (#peek struct stat, st_atimensec) stat :: IO (#type long)
+ let frac = toInteger nsec % 10^9
+#elif HAVE_STRUCT_STAT_ST_ATIME_N
+ nsec <- (#peek struct stat, st_atime_n) stat :: IO (#type int)
+ let frac = toInteger nsec % 10^9
+#elif HAVE_STRUCT_STAT_ST_UATIME
+ usec <- (#peek struct stat, st_uatime) stat :: IO (#type int)
+ let frac = toInteger usec % 10^6
+#else
+ let frac = 0
+#endif
+ return $ fromRational $ toRational sec + frac
+
+modificationTimeHiRes (FileStatus stat) =
+ unsafePerformIO $ withForeignPtr stat $ \stat -> do
+ sec <- (#peek struct stat, st_mtime) stat :: IO EpochTime
+#ifdef HAVE_STRUCT_STAT_ST_MTIM
+ nsec <- (#peek struct stat, st_mtim.tv_nsec) stat :: IO (#type long)
+ let frac = toInteger nsec % 10^9
+#elif HAVE_STRUCT_STAT_ST_MTIMESPEC
+ nsec <- (#peek struct stat, st_mtimespec.tv_nsec) stat :: IO (#type long)
+ let frac = toInteger nsec % 10^9
+#elif HAVE_STRUCT_STAT_ST_MTIMENSEC
+ nsec <- (#peek struct stat, st_mtimensec) stat :: IO (#type long)
+ let frac = toInteger nsec % 10^9
+#elif HAVE_STRUCT_STAT_ST_MTIME_N
+ nsec <- (#peek struct stat, st_mtime_n) stat :: IO (#type int)
+ let frac = toInteger nsec % 10^9
+#elif HAVE_STRUCT_STAT_ST_UMTIME
+ usec <- (#peek struct stat, st_umtime) stat :: IO (#type int)
+ let frac = toInteger usec % 10^6
+#else
+ let frac = 0
+#endif
+ return $ fromRational $ toRational sec + frac
+
+statusChangeTimeHiRes (FileStatus stat) =
+ unsafePerformIO $ withForeignPtr stat $ \stat -> do
+ sec <- (#peek struct stat, st_ctime) stat :: IO EpochTime
+#ifdef HAVE_STRUCT_STAT_ST_CTIM
+ nsec <- (#peek struct stat, st_ctim.tv_nsec) stat :: IO (#type long)
+ let frac = toInteger nsec % 10^9
+#elif HAVE_STRUCT_STAT_ST_CTIMESPEC
+ nsec <- (#peek struct stat, st_ctimespec.tv_nsec) stat :: IO (#type long)
+ let frac = toInteger nsec % 10^9
+#elif HAVE_STRUCT_STAT_ST_CTIMENSEC
+ nsec <- (#peek struct stat, st_ctimensec) stat :: IO (#type long)
+ let frac = toInteger nsec % 10^9
+#elif HAVE_STRUCT_STAT_ST_CTIME_N
+ nsec <- (#peek struct stat, st_ctime_n) stat :: IO (#type int)
+ let frac = toInteger nsec % 10^9
+#elif HAVE_STRUCT_STAT_ST_UCTIME
+ usec <- (#peek struct stat, st_uctime) stat :: IO (#type int)
+ let frac = toInteger usec % 10^6
+#else
+ let frac = 0
+#endif
+ return $ fromRational $ toRational sec + frac
+
-- | Checks if this file is a block device.
isBlockDevice :: FileStatus -> Bool
-- | Checks if this file is a character device.
diff --git a/configure.ac b/configure.ac
index ebf708d..9461452 100644
--- a/configure.ac
+++ b/configure.ac
@@ -34,6 +34,22 @@ AC_CHECK_FUNCS([ptsname])
AC_CHECK_FUNCS([setitimer])
AC_CHECK_FUNCS([readdir_r])
+AC_CHECK_MEMBERS([struct stat.st_atim])
+AC_CHECK_MEMBERS([struct stat.st_mtim])
+AC_CHECK_MEMBERS([struct stat.st_ctim])
+AC_CHECK_MEMBERS([struct stat.st_atimespec])
+AC_CHECK_MEMBERS([struct stat.st_mtimespec])
+AC_CHECK_MEMBERS([struct stat.st_ctimespec])
+AC_CHECK_MEMBERS([struct stat.st_atimensec])
+AC_CHECK_MEMBERS([struct stat.st_mtimensec])
+AC_CHECK_MEMBERS([struct stat.st_ctimensec])
+AC_CHECK_MEMBERS([struct stat.st_atime_n])
+AC_CHECK_MEMBERS([struct stat.st_mtime_n])
+AC_CHECK_MEMBERS([struct stat.st_ctime_n])
+AC_CHECK_MEMBERS([struct stat.st_uatime])
+AC_CHECK_MEMBERS([struct stat.st_umtime])
+AC_CHECK_MEMBERS([struct stat.st_uctime])
+
# Additional temp functions
AC_CHECK_FUNCS([mkstemps mkdtemp])
diff --git a/tests/fileStatus.hs b/tests/fileStatus.hs
index e1d1661..262d396 100644
--- a/tests/fileStatus.hs
+++ b/tests/fileStatus.hs
@@ -83,7 +83,7 @@ getStatus f = do
return (fs, ls)
--- Yay for 17-element tuples!
+-- Yay for 20-element tuples!
statusElements fs = (,)
(deviceID fs
,fileMode fs
@@ -93,8 +93,11 @@ statusElements fs = (,)
,specialDeviceID fs
,fileSize fs
,accessTime fs
+ ,accessTimeHiRes fs
,modificationTime fs
+ ,modificationTimeHiRes fs
,statusChangeTime fs
+ ,statusChangeTimeHiRes fs
)
(isBlockDevice fs
,isCharacterDevice fs
diff --git a/tests/fileStatusByteString.hs b/tests/fileStatusByteString.hs
index 35d52d8..ec492b3 100644
--- a/tests/fileStatusByteString.hs
+++ b/tests/fileStatusByteString.hs
@@ -82,7 +82,7 @@ getStatus f = do
return (fs, ls)
--- Yay for 17-element tuples!
+-- Yay for 20-element tuples!
statusElements fs = (,)
(deviceID fs
,fileMode fs
@@ -92,8 +92,11 @@ statusElements fs = (,)
,specialDeviceID fs
,fileSize fs
,accessTime fs
+ ,accessTimeHiRes fs
,modificationTime fs
+ ,modificationTimeHiRes fs
,statusChangeTime fs
+ ,statusChangeTimeHiRes fs
)
(isBlockDevice fs
,isCharacterDevice fs
diff --git a/unix.cabal b/unix.cabal
index 59fe0ad..e425f5e 100644
--- a/unix.cabal
+++ b/unix.cabal
@@ -78,7 +78,8 @@ Library
System.Posix.Terminal.Common
build-depends: base >= 4.2 && < 4.7,
- bytestring >= 0.9.2.0 && < 0.11
+ bytestring >= 0.9.2.0 && < 0.11,
+ time
extensions: CPP, ForeignFunctionInterface, EmptyDataDecls
if impl(ghc >= 7.1)
extensions: NondecreasingIndentation