nwaples / rardecode

A go package for reading RAR archives.
BSD 2-Clause "Simplified" License
124 stars 28 forks source link

rardecode: archive continues in next volume #13

Closed tomnewton closed 7 years ago

tomnewton commented 7 years ago

If you have the following files:

myarchive.rar myarchive.r00 myarchive.r01

what pattern should be used with your library to extract the single output file across these three parts of the archive?

I've tried a few different ways and have run into issues, but I think I'm just not using the library as intended. I see:

rardecode: archive continues in next volume

but that error is internal, so I don't think I'm supposed to handle it.

If I progress to the next file ( .r00 ) I get:

rardecode: invalid file block

nwaples commented 7 years ago

Did you use NewReader to open the archive? Thats the sort of error you would get if you did. Ive added some comments to clarify that OpenReader should be used for multi-volume archives. With OpenReader it will open all the archive files for you automatically. You should not have to do it manually.

tomnewton commented 7 years ago

I did. I found one bug which appears to have caused this in archive15.go. I have forked and will submit a pull request.

Another question though... how much do you know about multi-part rar naming conventions?

I have come across an archive in my testing that seems to use .s00 instead of .r100, and s01 instead of .r101. This wasn't handled in nextVolumeName. I've patched it too - but maybe incorrectly depending on if you can shed some light on the multi-part rar naming convention?

nwaples commented 7 years ago

All the code I wrote was based off the unrar C++ code. If it implements something in a certain way, then thats pretty much the standard. There is a NextVolumeName() function in pathfn.cpp. I can now see I didn't fully implement it. There is new style archive naming where a new character is added when the archive number overflows. This is what happens now. But there is an old style which if there is a character to the left of the digits in the file extension, it increments it. If there isn't one, the highest digit is set to 'A'.

Regarding the other error. I notice on line 426 of archive15.go I commented that 1.5 archive files may not have an end block. I never had any older samples to test with so never got back to it. I wasn't sure if end block's may not exist only in the intermediate files in the archive, or if the last file might not have an end block as well. With your fix when you get to the end of the archive, does requesting the next file produce an 'archive continues in next volume' error? To deal with no end of file block in the last file in the archive will require reworking of EOF and end of archive handling. I probably should create an endOfArchive error instead of using io.EOF so I can distinguish between them in packedFileReader, volume, etc.

tomnewton commented 7 years ago

I had to do this to get it to work on some archives:

https://github.com/tomnewton/rardecode/commit/bfb7813860adde1d62e3fcc1724eed7513da8c5b

nwaples commented 7 years ago

Ill have to look into it more. I did a quick test with that fix and it failed on multi volume archives created with the -en flag for rar command line.

I submitted a fix for the multipart rar file naming that should fix your problem. It should act much more like unrar/winrar now.

nwaples commented 7 years ago

I committed a fix that should cover your fix case and some more. Let me know if these fixes resolve your problems.

Maythink commented 7 years ago

how can I use this package?can you show me an example? thanks!

tomnewton commented 7 years ago

I think this package still needs a bit of work - but check with @nwaples

I resorted to installing the standard command line tool and calling it with:

// Unrar ...
func Unrar(rarFile string) error {
    destination := viper.GetString("CompletedDir")
    cmd := exec.Command("unrar", "e", rarFile, destination)
    var out bytes.Buffer
    mr := io.MultiWriter(&out, os.Stdout)
    cmd.Stdout = mr
    err := cmd.Run()
    if err != nil {
        return err
    }
    return nil
}
nwaples commented 7 years ago

I just created an issue #14 to create some example documentation. Its usage is similar to the standard library archive/tar package. If you wan't a simple package to extract archives for you, then there is https://github.com/mholt/archiver . It uses this package, but does all the work of creating files, directories etc.

@tomnewton did the fix I put in solve your problem? If the package still has issues, I would like to fix them.

jkotra commented 7 years ago

use gorar instead : https://github.com/jkotra/gorar/

KyleSanderson commented 2 years ago

is this still true? There's an issue in mholt/archiver saying there's no support for multi-file rars, and it's using this library...