diff options
-rw-r--r-- | System/Posix/Files.hsc | 1 | ||||
-rw-r--r-- | System/Posix/Files/ByteString.hsc | 1 | ||||
-rw-r--r-- | System/Posix/Files/Common.hsc | 78 | ||||
-rw-r--r-- | configure.ac | 16 | ||||
-rw-r--r-- | tests/fileStatus.hs | 5 | ||||
-rw-r--r-- | tests/fileStatusByteString.hs | 5 | ||||
-rw-r--r-- | unix.cabal | 3 |
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 @@ -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 |