File: tarzipuncompressor.cpp

package info (click to toggle)
qflipper 1.3.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 12,320 kB
  • sloc: cpp: 18,500; sh: 247; ansic: 191; xml: 38; python: 14; makefile: 5
file content (69 lines) | stat: -rw-r--r-- 2,102 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include "tarzipuncompressor.h"

#include <QDebug>
#include <QFutureWatcher>
#include <QtConcurrent/QtConcurrentRun>

#include "tararchive.h"
#include "tarziparchive.h"
#include "tempdirectories.h"

TarZipUncompressor::TarZipUncompressor(QFile *tarZipFile, const QDir &targetDir, QObject *parent):
    QObject(parent),
    m_tarZipArchive(new TarZipArchive(tarZipFile, this)),
    m_targetDir(targetDir)
{
    connect(m_tarZipArchive, &TarZipArchive::ready, this, &TarZipUncompressor::onArchiveReady);
}

void TarZipUncompressor::onArchiveReady()
{
    auto *watcher = new QFutureWatcher<void>(this);

    connect(watcher, &QFutureWatcherBase::finished, this, &TarZipUncompressor::finished);
#if QT_VERSION < 0x060000
    watcher->setFuture(QtConcurrent::run(this, &TarZipUncompressor::extractFiles));
#else
    watcher->setFuture(QtConcurrent::run(&TarZipUncompressor::extractFiles, this));
#endif
}

void TarZipUncompressor::extractFiles()
{
    const auto fileInfos = m_tarZipArchive->archiveIndex()->root()->toPreOrderList();

    for(const auto &fileInfo : fileInfos) {
        const auto &absolutePath = fileInfo.absolutePath;

        if(absolutePath.isEmpty()) {
            continue;
        } else if(fileInfo.type == FileNode::Type::Directory) {
            m_targetDir.mkpath(absolutePath);
        } else if(!extractFile(absolutePath, m_targetDir.absoluteFilePath(absolutePath))) {
            break;
        }
    }
}

bool TarZipUncompressor::extractFile(const QString &src, const QString &dst)
{
    // TODO: Write files to disk in chunks
    // Preferably rewrite all tar.gz operations in stream-friendly style
    // with no intermediate files

    QFile file(dst);
    // TODO: check for errors
    if(!file.open(QIODevice::WriteOnly)) {
        setError(BackendError::DiskError, file.errorString());
        return false;
    }

    const auto fileData = m_tarZipArchive->archiveIndex()->fileData(src);
    if(file.write(fileData) != fileData.size()) {
        setError(BackendError::DiskError, file.errorString());
        return false;
    }

    file.close();
    return true;
}