packages feed

darcs-2.3.0: src/win32/System/Posix/Files.hsc

{-# OPTIONS_GHC -cpp #-}
module System.Posix.Files where

import Foreign.Marshal.Alloc ( allocaBytes )
import Foreign.C.Error ( throwErrnoIfMinus1Retry, throwErrnoPathIf_ )
import Foreign.C.String ( withCString, withCWString, CWString )
import Foreign.C.Types ( CTime, CInt )
import Foreign.Ptr ( Ptr, nullPtr )

import System.Posix.Internals
          ( FDType, CStat, c_fstat, lstat, 
            sizeof_stat, statGetType, 
            st_mode, st_size, st_mtime,
            s_isreg, s_isdir, s_isfifo, c_stat )
import System.Posix.Types ( Fd(..), CMode, EpochTime, FileMode )

import Data.Bits ( (.|.) )

#if mingw32_HOST_OS
import Data.Int ( Int64 )
#else
import System.Posix.Types ( FileOffset )
#endif

##if mingw32_HOST_OS
type FileOffset = Int64
##endif

data FileStatus = FileStatus {
    fst_type :: FDType,
    fst_mode :: CMode,
    fst_mtime :: CTime,
    fst_size :: FileOffset
 }

getFdStatus :: Fd -> IO FileStatus
getFdStatus (Fd fd) = do
  do_stat (c_fstat fd)

do_stat :: (Ptr CStat -> IO CInt) -> IO FileStatus
do_stat stat_func = do
  allocaBytes sizeof_stat $ \p -> do
    throwErrnoIfMinus1Retry "do_stat" $
      stat_func p
    tp <- statGetType p
    mode <- st_mode p
    mtime <- st_mtime p
    size <- st_size p
    return (FileStatus tp mode mtime (fromIntegral size))

isNamedPipe :: FileStatus -> Bool
isNamedPipe = s_isfifo . fst_mode

isDirectory :: FileStatus -> Bool
isDirectory = s_isdir . fst_mode

isRegularFile :: FileStatus -> Bool
isRegularFile = s_isreg . fst_mode

isSymbolicLink :: FileStatus -> Bool
isSymbolicLink = const False

linkCount :: FileStatus -> Int
linkCount _ = 1

modificationTime :: FileStatus -> EpochTime
modificationTime = fst_mtime

fileSize :: FileStatus -> FileOffset
fileSize = fst_size

fileMode :: a -> ()
fileMode _ = ()

setFileMode :: FilePath -> () -> IO ()
setFileMode _ _ = return ()

#include <sys/stat.h>
stdFileMode :: FileMode
stdFileMode = (#const S_IRUSR) .|. (#const S_IWUSR)

getFileStatus :: FilePath -> IO FileStatus
getFileStatus fp =
  do_stat (\p -> (fp `withCString` (`c_stat` p)))

-- lstat is broken on win32 with at least GHC 6.10.3
getSymbolicLinkStatus :: FilePath -> IO FileStatus
##if mingw32_HOST_OS
getSymbolicLinkStatus = getFileStatus
##else
getSymbolicLinkStatus fp =
  do_stat (\p -> (fp `withCString` (`lstat` p)))
##endif

#define _WIN32_WINNT 0x0500
foreign import stdcall "winbase.h CreateHardLinkW" c_CreateHardLink :: CWString -> CWString -> Ptr a -> IO CInt

createLink :: FilePath -> FilePath -> IO ()
createLink old new = withCWString old $ \c_old -> withCWString new $ \c_new ->
	throwErrnoPathIf_ (==0) "createLink" new $
		c_CreateHardLink c_new c_old nullPtr