【问题标题】:Extracting .tar.gz using libarchive on UNC path?在 UNC 路径上使用 libarchive 提取 .tar.gz?
【发布时间】:2017-09-16 21:38:40
【问题描述】:

我正在尝试使用libarchive.tar.gz 文件提取到当前文件夹。测试机器是否在虚拟框下运行win7 64bit。如果我在C:\.vdi 磁盘)中执行此操作,它工作正常,但是在E:\(来自主机的共享文件夹)上失败。基于此

Can't create '\\?\e:\folder\file'

错误消息我认为问题是 UNC 路径。用libarchive可以处理吗?

这是我的代码:

#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;
    }
}

我想我可以先使用https://stackoverflow.com/a/2324777/781743 和 chdir 到非 unc 路径(如果存在),应该可以吗?但是有没有办法让libarchive 直接支持UNC 路径?

【问题讨论】:

    标签: c++ c windows unc libarchive


    【解决方案1】:

    这对我有用 [详细初始值为 0,do_extract 为 1,标志设置为 ARCHIVE_EXTRACT_TIME]

    struct archive *a;
    struct archive *ext;
    struct archive_entry *entry;
    int r;
    
    a = archive_read_new();
    ext = archive_write_disk_new();
    archive_write_disk_set_options(ext, flags);
    /*
     * Note: archive_write_disk_set_standard_lookup() is useful
     * here, but it requires library routines that can add 500k or
     * more to a static executable.
     */
    archive_read_support_format_tar(a);
    archive_read_support_filter_gzip(a);
    /*
     * On my system, enabling other archive formats adds 20k-30k
     * each.  Enabling gzip decompression adds about 20k.
     * Enabling bzip2 is more expensive because the libbz2 library
     * isn't very well factored.
     */
    if (filename != NULL && strcmp(filename, "-") == 0)
        filename = NULL;
    if ((r = archive_read_open_filename(a, filename, 10240)))
        fail("archive_read_open_filename()",
            archive_error_string(a), r);
    for (;;) {
        r = archive_read_next_header(a, &entry);
        if (r == ARCHIVE_EOF)
            break;
        if (r != ARCHIVE_OK)
            fail("archive_read_next_header()",
                archive_error_string(a), 1);
        if (verbose && do_extract)
            msg("x ");
        if (verbose || !do_extract)
            msg(archive_entry_pathname(entry));
        if (do_extract) {
            r = archive_write_header(ext, entry);
            if (r != ARCHIVE_OK)
                warn("archive_write_header()",
                    archive_error_string(ext));
            else {
                copy_data(a, ext);
                r = archive_write_finish_entry(ext);
                if (r != ARCHIVE_OK)
                    fail("archive_write_finish_entry()",
                        archive_error_string(ext), 1);
            }
        }
        if (verbose || !do_extract)
            msg("\n");
    }
    archive_read_close(a);
    archive_read_free(a);
    
    archive_write_close(ext);
    archive_write_free(ext);
    exit(0);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多