content: 
  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]
  
  