我正在尝试使用<form />
将libarchive
文件解压缩到当前文件夹。如果win7 64bit在虚拟机箱下运行,请测试机器。如果我在.tar.gz
(C:\
磁盘)中执行它,它可以正常工作,但它在.vdi
(来自主机的共享文件夹)上失败。基于此
E:\
错误消息我认为问题是UNC路径。是否可以使用Can't create '\\?\e:\folder\file'
处理它?</ p>
这是我的代码:
libarchive
我想我可以首先使用https://stackoverflow.com/a/2324777/781743和chdir到非unc路径(如果存在),这应该有用吗?但有没有办法直接提出#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;
}
}
支持libarchive
路径?
答案 0 :(得分:0)
这对我有用 [详细初始值为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);