|
| 1 | +{-# LANGUAGE LambdaCase #-} |
1 | 2 | module Codec.Archive.Unpack ( hsEntries |
2 | 3 | , unpackEntriesFp |
3 | 4 | , unpackArchive |
@@ -96,16 +97,26 @@ unpackEntriesFp a fp = do |
96 | 97 | case res of |
97 | 98 | Nothing -> pure () |
98 | 99 | Just x -> do |
99 | | - preFile <- liftIO $ archiveEntryPathname x |
100 | | - file <- liftIO $ peekCString preFile |
101 | | - let file' = fp </> file |
102 | | - liftIO $ withCString file' $ \fileC -> |
103 | | - archiveEntrySetPathname x fileC |
104 | | - ignore $ archiveReadExtract a x archiveExtractTime |
105 | | - liftIO $ archiveEntrySetPathname x preFile |
| 100 | + ignore . withPrefix fp x $ archiveReadExtract a x archiveExtractTime |
106 | 101 | ignore $ archiveReadDataSkip a |
107 | 102 | unpackEntriesFp a fp |
108 | 103 |
|
| 104 | +-- TODO: work with libarchive to get rid of this unsafe hack |
| 105 | +-- See https://github.com/libarchive/libarchive/issues/1203 |
| 106 | +withPrefix :: FilePath -> ArchiveEntryPtr -> IO a -> IO a |
| 107 | +withPrefix fp x inner = do |
| 108 | + file0 <- peekCString =<< archiveEntryPathname x |
| 109 | + withCString (fp </> file0) $ archiveEntrySetPathname x |
| 110 | + result <- archiveEntryFiletype x >>= \case |
| 111 | + Nothing -> archiveEntryHardlink x >>= peekCString >>= \target0 -> do |
| 112 | + withCString (fp </> target0) $ archiveEntrySetHardlink x |
| 113 | + result <- inner |
| 114 | + withCString target0 $ archiveEntrySetHardlink x |
| 115 | + return result |
| 116 | + _ -> inner |
| 117 | + withCString file0 $ archiveEntrySetPathname x |
| 118 | + return result |
| 119 | + |
109 | 120 | readBS :: Ptr Archive -> Int -> IO BS.ByteString |
110 | 121 | readBS a sz = |
111 | 122 | allocaBytes sz $ \buff -> |
|
0 commit comments