views:

945

answers:

2

I need to create a tarball of a directory and then compress it with bz2 in C++. Is there any decent tutorial on using libtar and libbz2?

A: 

Assuming this isn't just a "how can I do this" question, then the obvious way is to fork/exec GNU tar to do it for you. The easiest way is with the system(3) library routine:

  system("/path/to/gtar cfj tarballname.tar.bz2 dirname");

According to this, there are example programs in the libtar disty.

Bzip's documentation includes a section on programming with libbz2.

Charlie Martin
Why is that the obvious way? If he's doing this a lot, the process overhead will become significant. Not to mention that this way he has full control over bzip's options. And of course, best to make sure you escape arguments correctly when calling system.
Matthew Flaschen
because it's simple, it does what's needed, and it's completely insensitive to any little details of the tar format etc. On a UNIX machine, at least, fork/exec is *relatively* cheap. So, "obvious" in the sense of "what's the simplest thing that could work?"
Charlie Martin
+5  A: 

Okay, I worked up a quick example for you. No error checking and various arbitrary decisions, but it works. libbzip2 has fairly good web documentation. libtar, not so much, but there are manpages in the package, an example, and a documented header file. The below can be built with g++ C++TarBz2.cpp -ltar -lbz2 -o C++TarBz2.exe:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <libtar.h>
#include <bzlib.h>
#include <unistd.h>

int main()
{
    TAR *pTar;
    char tarFilename[] = "file.tar";
    char srcDir[] = "dirToZip/";
    char extractTo[] = ".";

    tar_open(&pTar, tarFilename, NULL, O_WRONLY | O_CREAT, 0644, TAR_GNU);
    tar_append_tree(pTar, srcDir, extractTo);

    close(tar_fd(pTar));

    int tarFD = open(tarFilename, O_RDONLY);

    char tbz2Filename[] =  "file.tar.bz2";
    FILE *tbz2File = fopen(tbz2Filename, "wb");
    int bzError;
    const int BLOCK_MULTIPLIER = 7;
    BZFILE *pBz = BZ2_bzWriteOpen(&bzError, tbz2File, BLOCK_MULTIPLIER, 0, 0);

    const int BUF_SIZE = 10000;
    char* buf = new char[BUF_SIZE];
    ssize_t bytesRead;
    while((bytesRead = read(tarFD, buf, BUF_SIZE)) > 0)
    {
    BZ2_bzWrite(&bzError, pBz, buf, bytesRead);
    }
    BZ2_bzWriteClose(&bzError, pBz, 0, NULL, NULL);
    close(tarFD);
    remove(tarFilename);

    delete[] buf;

}
Matthew Flaschen