Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 19 additions & 19 deletions src/Codec/Archive/Unpack.hs
Original file line number Diff line number Diff line change
Expand Up @@ -96,28 +96,28 @@ unpackEntriesFp a fp = do
case res of
Nothing -> pure ()
Just x -> do
preFile <- liftIO $ archiveEntryPathname x
file <- liftIO $ peekCString preFile
let file' = fp </> file
liftIO $ withCString file' $ \fileC ->
archiveEntrySetPathname x fileC
ft <- liftIO $ archiveEntryFiletype x
case ft of
Just{} -> do
ignore $ archiveReadExtract a x archiveExtractTime
liftIO $ archiveEntrySetPathname x preFile
Nothing -> do
preHardlink <- liftIO $ archiveEntryHardlink x
hardlink <- liftIO $ peekCString preHardlink
let hardlink' = fp </> hardlink
liftIO $ withCString hardlink' $ \hl ->
archiveEntrySetHardlink x hl
ignore $ archiveReadExtract a x archiveExtractTime
liftIO $ archiveEntrySetPathname x preFile
liftIO $ archiveEntrySetHardlink x preHardlink
ignore . withPrefix fp x $ archiveReadExtract a x archiveExtractTime
ignore $ archiveReadDataSkip a
unpackEntriesFp a fp

-- TODO: work with libarchive to get rid of this unsafe hack
-- See https://github.com/libarchive/libarchive/issues/1203
withPrefix :: FilePath -> ArchiveEntryPtr -> IO a -> IO a
withPrefix fp x inner = do
file0 <- peekCString =<< archiveEntryPathname x
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't this mean the pointer to the original archive entry pathname is forgotten? Thus, the original pathname will never be freed.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Declaration is const char * archive_entry_pathname(struct archive_entry *a). Thus ownership for returned pointer is not transferred to caller as in char *strdup(const char*). It still owned by archive_entry structure.

You can find similar code in readEntry:

Entry
        <$> (peekCString =<< archiveEntryPathname entry)
        <*> readContents a entry
        -- ...

withCString (fp </> file0) $ archiveEntrySetPathname x
ft <- archiveEntryFiletype x
result <- case ft of
Just{} -> inner
Nothing -> do
target0 <- peekCString =<< archiveEntryHardlink x
withCString (fp </> target0) $ archiveEntrySetHardlink x
result <- inner
withCString target0 $ archiveEntrySetHardlink x
return result
withCString file0 $ archiveEntrySetPathname x
return result

readBS :: Ptr Archive -> Int -> IO BS.ByteString
readBS a sz =
allocaBytes sz $ \buff ->
Expand Down