c ++ - Udtrækning .tar.gz ved hjælp af libarchive på UNC sti?

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg prøver at bruge libarchive til at udpakke .tar.gz fil til den aktuelle mappe. Testmaskine, hvis win7 64bit kører under virtuel boks. Det virker fint, hvis jeg gør det i C: (.vdi disk), men det mislykkes på E: (delt mappe fra vært). Baseret på dette


Can't create '\?e:folderfile'


fejlmeddelelse Jeg antager, at problemet er UNC-sti. Er det muligt at håndtere det med libarchive?


Her er min kode:


#include <iostream>
#include <cstdio>
#include <stdexcept>

#include <archive.h>
#include <archive\_entry.h>

#include "utils.h"

int copy\_data(struct archive * ar, struct archive * aw) {
    int r;
    size\_t size;
    const void *buff;
    int64\_t offset;

    for (;;) {
        r = archive\_read\_data\_block(ar, &buff, &size, &offset);
        if (r == ARCHIVE\_EOF) {
            return (ARCHIVE\_OK);
        } else if (r < ARCHIVE\_OK) {
            return (r);
        }
        r = archive\_write\_data\_block(aw, buff, size, offset);
        if (r < ARCHIVE\_OK) {
            std::cerr << archive\_error\_string(aw) << std::endl;
            return (r);
        }
    }
}

void handle\_errors(archive * a, int r, const char * msg) {
    if (r < ARCHIVE\_OK) {
        std::cerr << archive\_error\_string(a) << std::endl;
    }
    if (r < ARCHIVE\_WARN) {
        throw std::runtime\_error(msg);
    }
};

void extract(std::string target\_file\_name) {
    struct archive * a = nullptr;
    struct archive * ext = nullptr;
    struct archive\_entry * entry = nullptr;
    int flags, r;

    /* Select which attributes we want to restore. */
    flags = ARCHIVE\_EXTRACT\_TIME;
    flags |= ARCHIVE\_EXTRACT\_UNLINK;
    flags |= ARCHIVE\_EXTRACT\_SECURE\_NODOTDOT;

    a = archive\_read\_new();
    if (!a) { throw std::runtime\_error("Cannot archive\_read\_new"); }
    On\_Scope\_Exit([&] { archive\_read\_free(a); });
    archive\_read\_support\_format\_tar(a);
    archive\_read\_support\_filter\_gzip(a);

    ext = archive\_write\_disk\_new();
    if (!ext) { throw std::runtime\_error("Cannot archive\_write\_disk\_new"); }
    On\_Scope\_Exit([&] { archive\_write\_close(ext); archive\_write\_free(ext); });
    archive\_write\_disk\_set\_options(ext, flags);
    archive\_write\_disk\_set\_standard\_lookup(ext);

    if ((r = archive\_read\_open\_filename(a, target\_file\_name.c\_str(), 10240))) {
        throw std::runtime\_error("Cannot archive\_read\_open\_filename");
    }
    On\_Scope\_Exit([&] { archive\_read\_close(a); });

    for (;;) {
        r = archive\_read\_next\_header(a, &entry);
        if (r == ARCHIVE\_EOF) {
            break;
        }
        handle\_errors(a, r, "Encountered error while reading header.");
        r = archive\_write\_header(ext, entry);
        if (r < ARCHIVE\_OK) {
            std::cerr << archive\_error\_string(ext) << std::endl;
        }
        else if (archive\_entry\_size(entry) > 0) {
            r = copy\_data(a, ext);
            handle\_errors(ext, r, "Encountered error while copy data.");
        }
        r = archive\_write\_finish\_entry(ext);
        handle\_errors(ext, r, "Encountered error while finishing entry.");
    }
}

int main(int, char**) {
    try {
        std::string tmp\_file\_name = "file.tar.gz";
        extract(tmp\_file\_name);
        return 0;
    } catch (std::exception & e) {
        std::cerr << e.what() << std::endl;
        return 1;
    }
}


Jeg antager, at jeg kunne bruge https://stackoverflow.com/a/2324777/781743 og chdir til non-unc-stien først (hvis den findes), det burde fungere? Men er der en måde at gøre libarchive støtte UNC stier direkte?

Bedste reference