2-- confirm that the filesystem type is a journaled FS type expected by Project:M36
3-- use statfs on Linux and macOS and GetVolumeInformation on Windows
4-- this could still be fooled with symlinks or by disabling journaling on filesystems that support that
5module ProjectM36.FSType where
7#if defined(mingw32_HOST_OS)
8# if defined(i386_HOST_ARCH)
9# define WINDOWS_CCONV stdcall
10# elif defined(x86_64_HOST_ARCH)
11# define WINDOWS_CCONV ccall
13import System.Win32.Types
14import Foreign.ForeignPtr
17import Foreign.Storable
19foreign import WINDOWS_CCONV unsafe "windows.h GetVolumePathNameW"
20 c_GetVolumePathName :: LPCTSTR -> LPTSTR -> DWORD -> IO BOOL
22foreign import WINDOWS_CCONV unsafe "windows.h GetVolumeInformationW"
23 c_GetVolumeInformation :: LPCTSTR -> LPTSTR -> DWORD -> LPDWORD -> LPDWORD -> LPDWORD -> LPTSTR -> DWORD -> IO BOOL
25#define FILE_SUPPORTS_USN_JOURNAL 0x02000000
27getVolumePathName :: FilePath -> IO String
28getVolumePathName path = do
29 let maxpathlen = 260 --ANSI MAX_PATH- we only care about the drive name anyway
30 withTString path $ \c_path -> do
31 fp_pathout <- mallocForeignPtrBytes maxpathlen
32 withForeignPtr fp_pathout $ \pathout -> do
33 failIfFalse_ ("GetVolumePathNameW " ++ path) (c_GetVolumePathName c_path pathout (fromIntegral maxpathlen))
36fsTypeSupportsJournaling :: FilePath -> IO Bool
37fsTypeSupportsJournaling path = do
38 -- get the drive path of the incoming path
39 drive <- getVolumePathName path
40 withTString drive $ \c_drive -> do
41 foreign_flags <- mallocForeignPtrBytes 8
42 withForeignPtr foreign_flags $ \ptr_fsFlags -> do
43 failIfFalse_ (unwords ["GetVolumeInformationW", path]) (c_GetVolumeInformation c_drive nullPtr 0 nullPtr nullPtr ptr_fsFlags nullPtr 0)
44 fsFlags <- peekByteOff ptr_fsFlags 0 :: IO Word64
45 pure (fsFlags .&. FILE_SUPPORTS_USN_JOURNAL /= 0)
49import Foreign.C.String
52--Darwin reports journaling directly in the fs flags
55foreign import ccall unsafe "cDarwinFSJournaled"
56 c_DarwinFSJournaled :: CString -> IO CInt
58fsTypeSupportsJournaling :: FilePath -> IO Bool
59fsTypeSupportsJournaling path =
60 withCString path $ \c_path -> do
61 ret <- throwErrnoIfMinus1 "statfs" (c_DarwinFSJournaled c_path)
62 pure (ret > (0 :: CInt))
67import Foreign.C.String
71--Linux cannot report journaling, so we just check the filesystem type as a proxy
73foreign import ccall unsafe "sys/vfs.h statfs"
74 c_statfs :: CString -> Ptr CStatFS -> IO CInt
76#if WORD_SIZE_IN_BITS == 64
78sizeofStructStatFS :: Int
79sizeofStructStatFS = 120
81#error 32-bit not supported due to sizeof struct statfs missing
83sizeofStructStatFS :: Int
84sizeofStructStatFS = undefined
87fsTypeSupportsJournaling :: FilePath -> IO Bool
88fsTypeSupportsJournaling path = do
89 struct_statfs <- mallocForeignPtrBytes sizeofStructStatFS
90 withCString path $ \c_path -> do
91 withForeignPtr struct_statfs $ \ptr_statfs -> do
92 throwErrnoIfMinus1_ "statfs" (c_statfs c_path ptr_statfs)
93 cfstype <- peekByteOff ptr_statfs 0 :: IO CFSType
94 let journaledFS = [0xEF53, --EXT3+4
96 0x52654973, --REISERFS
100 pure (elem cfstype journaledFS)
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list