0

I am trying to add a directory to a tar archive that I am creating. The archive is created, however, it has no files in it.

Here's the code I have using libarchive (directory is a QString of the path to the directory to be tarred.)

struct archive *a;
struct archive_entry *entry;
struct stat st;
char buff[8192];
size_t bytes_read;
int fd;

// the path of the output tarfile
QByteArray outArray = (directory + ".tar").toLocal8Bit();
char *outDirectory = outArray.data();

// the path to the input directory
QByteArray inputArray = directory.toLocal8Bit();
char *inputDirectory = inputArray.data();

QFileInfo inputInfo;
inputInfo.setFile(directory);

// the name of the directory
QByteArray pathArray = inputInfo.fileName().toLocal8Bit();
char *pathDirectory = pathArray.data();

a = archive_write_new();
archive_write_add_filter_gzip(a);
archive_write_set_format_pax_restricted(a);
archive_write_open_filename(a, outDirectory);

entry = archive_entry_new();
stat(inputDirectory, &st);

archive_entry_set_pathname(entry, pathDirectory);
archive_entry_set_filetype(entry, AE_IFDIR);
archive_entry_copy_stat(entry, &st);
archive_write_header(a, entry);

fd = open(inputDirectory, O_RDONLY);
bytes_read = read(fd, buff, sizeof(buff));
while (bytes_read > 0) {
    archive_write_data(a, buff, bytes_read);
    bytes_read = read(fd, buff, sizeof(buff));
}
close(fd);

archive_write_finish_entry(a);
archive_write_close(a);
archive_write_free(a);
lthreed
  • 444
  • 4
  • 11
  • Why don't you use archiving libraries from the Qt world, like Quazip or the one from KDE? Also, you want `directory.toLocal8Bit() + ".tar"` instead of `(directory + ".tar").toLocal8Bit()`. Also, I cannot possible imagine why you are not using QFile for the read. – László Papp Apr 28 '14 at 02:59

2 Answers2

3

Your code logic is incorrect. You are trying to read a directory, whereas you should read the files in the directory... You would need something like this to iterate the file through:

QDirIterator it("/etc", QDirIterator::Subdirectories);
while (it.hasNext())
    qDebug() << it.next();

This is a proof of concept code to fix your issue.

#include <QString>
#include <QByteArray>
#include <QFileInfo>
#include <QDebug>
#include <QDirIterator>

#include <archive.h>
#include <archive_entry.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main()
{
    QString directory = "/home/lpapp/tmp/stackoverflow/test";
    struct archive *a;
    struct archive_entry *entry;
    struct stat st;
    char buff[8192];
    size_t bytes_read;
    int fd;

    QByteArray outArray = directory.toLocal8Bit() + ".tar";
    char *outDirectory = outArray.data();
    qDebug() << outDirectory;

    QByteArray inputArray = directory.toLocal8Bit();
    char *inputDirectory = inputArray.data();
    qDebug() << inputDirectory;

    QFileInfo inputInfo;
    inputInfo.setFile(directory);

    // the name of the directory
    QByteArray pathArray = inputInfo.fileName().toLocal8Bit();
    char *pathDirectory = pathArray.data();
    qDebug() << pathDirectory;

    a = archive_write_new();
    archive_write_add_filter_gzip(a);
    archive_write_set_format_pax_restricted(a);
    archive_write_open_filename(a, outDirectory);

    QDirIterator it(directory, QDirIterator::Subdirectories);
    while (it.hasNext()) {
        entry = archive_entry_new();
        stat(inputDirectory, &st);

        archive_entry_set_pathname(entry, it.next().toLocal8Bit().constData());
        archive_entry_set_filetype(entry, AE_IFDIR);
        archive_entry_copy_stat(entry, &st);
        archive_write_header(a, entry);

        fd = open(inputDirectory, O_RDONLY);
        bytes_read = read(fd, buff, sizeof(buff));
        while (bytes_read > 0) {
            archive_write_data(a, buff, bytes_read);
            bytes_read = read(fd, buff, sizeof(buff));
        }
        close(fd);
        archive_entry_free(entry);

        archive_write_finish_entry(a);
        archive_write_close(a);
        archive_write_free(a);
    }

    return 0;
}

main.pro

TEMPLATE = app
TARGET = main
QT = core
LIBS += -larchive
SOURCES += main.cpp

Build and Run

qmake && make && ./main
László Papp
  • 51,870
  • 39
  • 111
  • 135
0

You could try my library , QArchive which is non-blocking and single threaded.

Here is a simple code to compress directory(which is recursively added by default).

#include <QCoreApplication>
#include <QDebug>
#include <QArchive>

int main(int argc, char** argv)  {
 QCoreApplication app(argc, argv);
 QArchive::DiskCompressor Compressor("test.7z");
 Compressor.addFiles("YourDirectoryToCompress"); // Add directory or file.
 QObject::connect(&Compressor , &QArchive::DiskCompressor::finished, [&]() {
    qDebug() << "Finished!";
    app.quit();
 });

 Compressor.start();
 return app.exec();
}
antonyjr
  • 61
  • 1
  • 5