tar-conduit-0.2.2: src/Data/Conduit/Tar/Types.hs
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE CPP #-}
-- | Module contains all the types necessary for tarball processing.
module Data.Conduit.Tar.Types
( Header(..)
, TarChunk(..)
, TarException(..)
, TarCreateException(..)
, FileType(..)
, FileInfo(..)
, FileOffset
, ByteCount
, UserID
, GroupID
, DeviceID
, EpochTime
, CUid(..)
, CGid(..)
, encodeFilePath
, decodeFilePath
, getFileInfoPath
) where
import Control.Exception (Exception)
import Data.ByteString (ByteString)
import Data.ByteString.Short (ShortByteString)
import Data.Typeable
import Data.Word
import System.Posix.Types
import qualified Data.ByteString.Char8 as S8
import Data.Text as T
import Data.Text.Encoding as T
import Data.Text.Encoding.Error as T
#if WINDOWS
import Data.Bits
import Foreign.Storable
newtype CUid =
CUid Word32
deriving ( Bounded
, Enum
, Eq
, Integral
, Num
, Ord
, Read
, Real
, Show
, Bits
, Storable
)
newtype CGid =
CGid Word32
deriving ( Bounded
, Enum
, Eq
, Integral
, Num
, Ord
, Read
, Real
, Show
, Bits
, Storable
)
type UserID = CUid
type GroupID = CGid
#endif
data FileType
= FTNormal
| FTHardLink
| FTSymbolicLink !ByteString
| FTCharacterSpecial
| FTBlockSpecial
| FTDirectory
| FTFifo
| FTOther !Word8
deriving (Show, Eq)
data FileInfo = FileInfo
{ filePath :: !ByteString -- ^ File path.
, fileUserId :: !UserID -- ^ Unix user id.
, fileUserName :: !ByteString -- ^ Unix user name.
, fileGroupId :: !GroupID -- ^ Unix group id.
, fileGroupName :: !ByteString -- ^ Unix group name.
, fileMode :: !FileMode -- ^ Unix file permissions
, fileSize :: !FileOffset -- ^ File size
, fileType :: !FileType -- ^ File type. `FTNormal`, `FTSymbolicLink`
-- and `FTDirectory` are the only ones
-- supported for now
, fileModTime :: !EpochTime -- ^ File modification timestamp
} deriving (Show, Eq)
data Header = Header
{ headerOffset :: !FileOffset
, headerPayloadOffset :: !FileOffset
, headerFileNameSuffix :: !ShortByteString
, headerFileMode :: !CMode
, headerOwnerId :: !UserID
, headerGroupId :: !GroupID
, headerPayloadSize :: !FileOffset
, headerTime :: !EpochTime
, headerLinkIndicator :: !Word8
, headerLinkName :: !ShortByteString
, headerMagicVersion :: !ShortByteString
, headerOwnerName :: !ShortByteString
, headerGroupName :: !ShortByteString
, headerDeviceMajor :: !DeviceID
, headerDeviceMinor :: !DeviceID
, headerFileNamePrefix :: !ShortByteString
}
deriving Show
data TarChunk
= ChunkHeader Header
| ChunkPayload !FileOffset !ByteString
| ChunkException TarException
deriving Show
-- | This the the exception type that is used in this module.
--
-- More constructors are susceptible to be added without bumping the major
-- version of this module.
data TarException
= NoMoreHeaders
| UnexpectedPayload !FileOffset
| IncompleteHeader !FileOffset
| IncompletePayload !FileOffset !ByteCount
| ShortTrailer !FileOffset
| BadTrailer !FileOffset
| InvalidHeader !FileOffset
| BadChecksum !FileOffset
| FileTypeError !FileOffset !Char !String
deriving (Show, Typeable)
instance Exception TarException
data TarCreateException
= FileNameTooLong !FileInfo
| TarCreationError !String
deriving (Show, Typeable)
instance Exception TarCreateException
-- | Convert `FilePath` into a UTF-8 encoded `ByteString`
encodeFilePath :: FilePath -> S8.ByteString
encodeFilePath = T.encodeUtf8 . T.pack
-- | Convert UTF-8 encoded `ByteString` back into the `FilePath`.
decodeFilePath :: S8.ByteString -> FilePath
decodeFilePath = T.unpack . T.decodeUtf8With T.lenientDecode
-- | Get the `FilePath`.
getFileInfoPath :: FileInfo -> FilePath
getFileInfoPath = decodeFilePath . filePath