module System.Directory.AccessTime (
getAccessTime, getAccessTimeResolution
) where
import System.Time
#ifdef UNIX
import Data.Time.Clock.POSIX
import System.Posix.Types
import System.Posix.Files
getAccessTime fp = fmap (epochTimeToClockTime . accessTime) $ getFileStatus fp
epochTimeToClockTime :: EpochTime -> ClockTime
epochTimeToClockTime x = TOD whole_secs (round fractional_picosecs)
where (whole_secs, fractional_sec) = properFraction (toRational x)
fractional_picosecs = 1000000000000 * fractional_sec
getAccessTimeResolution _ = return $ noTimeDiff { tdSec = 1 }
#elif defined(WINDOWS)
import Data.Bits
import Data.List (genericReplicate)
import Foreign.Ptr
import Control.Exception (bracket)
import System.FilePath.Windows
import System.Win32.File
import System.Win32.Time
import System.Win32.Types
getAccessTime fp = bracket (createFile fp gENERIC_READ (fILE_SHARE_WRITE .|. fILE_SHARE_READ) Nothing oPEN_EXISTING fILE_ATTRIBUTE_NORMAL Nothing) closeHandle $ \h -> do
(_creation_time, access_time, _write_time) <- getFileTime h
fmap systemTimeToClockTime $ fileTimeToSystemTime access_time
systemTimeToClockTime :: SYSTEMTIME -> ClockTime
systemTimeToClockTime time = toClockTime $ CalendarTime {
ctYear = fromIntegral (wYear time),
ctMonth = toEnum (fromIntegral (wMonth time)),
ctDay = fromIntegral (wDay time),
ctHour = fromIntegral (wHour time),
ctMin = fromIntegral (wMinute time),
ctSec = fromIntegral (wSecond time),
ctPicosec = fromIntegral (wMilliseconds time) * 1000000000,
ctWDay = error "Documented as ignored: ctWDay",
ctYDay = error "Documented as ignored: ctYDay",
ctTZName = error "Documented as ignored: ctTZName",
ctTZ = 0,
ctIsDST = error "Documented as ignored: ctIsDST"
}
getAccessTimeResolution fp = do
fs <- getVolumeFileSystem (takeDrive fp)
return $ case fs of "NTFS" -> noTimeDiff { tdHour = 1 }
'F':'A':'T':_ -> noTimeDiff { tdDay = 1 }
_ -> noTimeDiff { tdSec = 1 }
foreign import stdcall "Windows.h GetVolumeInformationW" c_getVolumeInformationW :: LPCTSTR
-> LPTSTR
-> DWORD
-> LPDWORD
-> LPDWORD
-> LPDWORD
-> LPTSTR
-> DWORD
-> IO BOOL
getVolumeFileSystem :: FilePath -> IO String
getVolumeFileSystem fp = withTString fp $ \fp_tstr -> withTString (genericReplicate fs_len ' ') $ \fs_tstr -> do
failIfFalse_ ("GetVolumeInformation " ++ show fp) $ c_getVolumeInformationW fp_tstr nullPtr 0 nullPtr nullPtr nullPtr fs_tstr fs_len
peekTString fs_tstr
where
fs_len = mAX_PATH + 1
mAX_PATH = 260
#else
#error Unsupported platform
#endif
getAccessTime :: FilePath -> IO ClockTime
getAccessTimeResolution :: FilePath -> IO TimeDiff