+
+module Tar where
+
+import Data.Either
+import Data.List
+import System.Exit
+import System.Process
+
+import Utils
+
+readTarLines :: FilePath -> IO [TarLine]
+readTarLines fp
+ = do (ec, out, err) <- readProcessWithExitCode "tar" ["-jtvf", fp] ""
+ case (ec, err) of
+ (ExitSuccess, []) ->
+ case parseTarLines fp out of
+ Left errs -> die errs
+ Right tls -> return tls
+ _ ->
+ die ["Failed running tar -jtvf " ++ show fp,
+ "Exit code: " ++ show ec,
+ "Stderr: " ++ show err]
+
+parseTarLines :: FilePath -> String -> Either Errors [TarLine]
+parseTarLines fp xs
+ = case partitionEithers (zipWith (parseTarLine fp) [1..] (lines xs)) of
+ ([], tls) -> Right tls
+ (errss, _) -> Left (intercalate [""] errss)
+
+data TarLine = TarLine {
+ tlPermissions :: String,
+ tlUser :: String,
+ tlGroup :: String,
+ tlSize :: Integer,
+ tlDateTime :: String,
+ tlFileName :: FilePath
+ }
+
+parseTarLine :: FilePath -> Int -> String -> Either Errors TarLine
+parseTarLine fp line str
+ = case re "^([^ ]+) ([^ ]+)/([^ ]+) +([0-9]+) ([^ ]+ [^ ]+) ([^ ]+)$"
+ str of
+ Just [perms, user, grp, sizeStr, dateTime, filename] ->
+ case maybeRead sizeStr of
+ Just size ->
+ Right $ TarLine {
+ tlPermissions = perms,
+ tlUser = user,
+ tlGroup = grp,
+ tlSize = size,
+ tlDateTime = dateTime,
+ tlFileName = filename
+ }
+ _ -> error "Can't happen: Can't parse size"
+ _ ->
+ Left ["In " ++ show fp ++ ", at line " ++ show line,
+ "Tar line doesn't parse: " ++ show str]
+