QArchive icon indicating copy to clipboard operation
QArchive copied to clipboard

QArchive::Extractor start() call without directory.

Open krab opened this issue 4 years ago • 10 comments

Select your issue type: (check at least one)

  • [x] Bug
  • [ ] Question
  • [ ] Suggestion
  • [ ] Other (please describe):

example code

    auto archive = new QFile("/home/krab/Downloads/test1.tar");
    qDebug() << archive->open(QIODevice::ReadOnly);
    auto extractor = new QArchive::Extractor();
    extractor->setArchive(archive);
    connect(extractor, &QArchive::Extractor::info, this, [this] (QJsonObject json) {
        qDebug() << json;
    });
    connect(extractor, &QArchive::Extractor::error, this, [this] (short code) {
        if(code == QArchive::ArchivePasswordNeeded ||
                code == QArchive::ArchivePasswordIncorrect) {
            return;
        }
        qInfo() << "[-] An error has occured :: " << QArchive::errorCodeToString(code) ;
        return;
    });
    extractor->getInfo();
    extractor->start();

When you forget to set extractor->setOutputDirectory("/path/to/dir) and call start() then qarchive doesnt work properly.

QFileDevice::seek: IODevice is not open
QFileDevice::seek: IODevice is not open
[-] An error has occured ::  "QArchive::ArchiveCorrupted"

It writes 2 times qfiledevice error probably from short ExtractorPrivate::checkOutputDirectory() { function and also sets wrong error code ArchiveCorrupted on getInfo(), which is wrong, i could remove start() and json object will created and printed to console.

krab avatar Nov 23 '21 14:11 krab

@krab QArchive::Extractor is not documented and it's actually intended for internal use. So using it is not recommended.

I tested your code and it seems to work without having to set setOutputDirectory. I think I need more info on this.

This might be a edge case I'm missing.

Does this work with the public class QArchive::DiskExtractor. Also make sure your input QIODevice is seekable, it should not be sequential (If you are directly using it with something like QNetworkReply then it will not work since it's sequential).

antony-jr avatar Nov 23 '21 18:11 antony-jr

I tested your code and it seems to work without having to set setOutputDirectory. I think I need more info on this.

full example above with getInfo() and with start()?

Here is my test1.tar archive made from msedge binaries (symlinks and one hardlink) https://drive.google.com/file/d/12ZnKIDQdoOu2_PxEZ3zo_GetShvMw8qy/view?usp=sharing

krab avatar Nov 24 '21 11:11 krab

Anyway it seems like QArchive doesn't support extraction of single file / list of files from archive?

krab avatar Nov 24 '21 11:11 krab

I'm trying to reproduce your issue. I will ping you when I find something.

antony-jr avatar Nov 24 '21 14:11 antony-jr

Anyway it seems like QArchive doesn't support extraction of single file / list of files from archive?

It does support that. see addFilter.

antony-jr avatar Nov 24 '21 14:11 antony-jr

@krab as I said the Extractor class is not for public use and will not be documented. Please use MemoryExtractor or DiskExtractor. See documentation at https://antonyjr.in/QArchive

Here is the code I used.

#include <QDebug>
#include <QFile>
#include <QArchive/QArchive> 
#include <QJsonObject>

int main(int ac, char **av) {
    if(ac < 2) {
        qDebug() << "Usage: " << av[0] << " [ARCHIVE PATH]";
        return 0;
    }

    QCoreApplication app(ac, av);

    /* Get Archive Information. */
    QString ArchivePath = QString(av[1]);

    auto archive = new QFile(ArchivePath);
    qDebug() << archive->open(QIODevice::ReadOnly);
    
    // Please don't use Extractor class though.
    auto extractor = new QArchive::Extractor();
    extractor->setArchive(archive);
    QObject::connect(extractor, &QArchive::Extractor::info, [&] (QJsonObject json) {
        qDebug() << json;
    });
    
    QObject::connect(extractor, &QArchive::Extractor::error, [&](short code) {
        if(code == QArchive::ArchivePasswordNeeded ||
                code == QArchive::ArchivePasswordIncorrect) {
            return;
        }
        qInfo() << "[-] An error has occured :: " << QArchive::errorCodeToString(code) ;
        return;
    });
   
    QObject::connect(extractor, &QArchive::Extractor::diskFinished, &app, &QCoreApplication::quit);

    extractor->getInfo();
    extractor->start();
    return app.exec();
}

and it seems to work.

I successfully extracted the test archive you give with no issue.

libarchive version information,

bsdtar --version
bsdtar 3.5.2 - libarchive 3.5.2 zlib/1.2.11 liblzma/5.2.5 bz2lib/1.0.8 liblz4/1.9.3 libzstd/1.5.0

antony-jr avatar Nov 24 '21 14:11 antony-jr

@krab is this actually resolved??

antony-jr avatar Nov 24 '21 14:11 antony-jr

Works if i do start and then getInfo, but not otherwise. Probably some sort of race conditions or something.

krab avatar Nov 24 '21 15:11 krab

This is concerning, I will investigate more on this. Some info on the distro you use and how you installed QArchive. Thanks.

antony-jr avatar Nov 24 '21 15:11 antony-jr

Fedora 35 with KDE. Debug build into /usr prefix.

Also CMAKE_INSTALL_LIBDIR=lib64

krab avatar Nov 24 '21 15:11 krab

It works now with the latest master.

antony-jr avatar Oct 30 '22 18:10 antony-jr