17 #ifndef __STOUT_ARCHIVER_HPP__ 18 #define __STOUT_ARCHIVER_HPP__ 21 #include <archive_entry.h> 41 const std::string& source,
42 const std::string& destination,
43 const int flags = ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_SECURE_NODOTDOT)
46 std::unique_ptr<struct archive, std::function<void(struct archive*)>> reader(
48 [](
struct archive* p) {
49 archive_read_close(p);
54 archive_read_support_format_all(reader.get());
55 archive_read_support_filter_all(reader.get());
57 std::unique_ptr<struct archive, std::function<void(struct archive*)>> writer(
58 archive_write_disk_new(),
59 [](
struct archive* p) {
60 archive_write_close(p);
61 archive_write_free(p);
64 archive_write_disk_set_options(writer.get(),
flags);
65 archive_write_disk_set_standard_lookup(writer.get());
73 return Error(fd.error());
77 int fd_real = fd->crt();
79 int fd_real = fd.get();
90 ~Closer() { ::_close(fd_value); }
96 const size_t archive_block_size = 10240;
97 int result = archive_read_open_fd(reader.get(), fd_real, archive_block_size);
98 if (result != ARCHIVE_OK) {
99 return Error(archive_error_string(reader.get()));
105 struct archive_entry* entry;
106 result = archive_read_next_header(reader.get(), &entry);
108 if (result == ARCHIVE_EOF) {
110 }
else if (result <= ARCHIVE_WARN) {
112 std::string(
"Failed to read archive header: ") +
113 archive_error_string(reader.get()));
118 if (!destination.empty()) {
120 const char* hardlink_target = archive_entry_hardlink_utf8(entry);
122 if (hardlink_target !=
nullptr) {
123 archive_entry_update_hardlink_utf8(
125 path::join(destination, hardlink_target).c_str());
128 archive_entry_update_pathname_utf8(
130 path::join(destination, archive_entry_pathname_utf8(entry)).c_str());
133 result = archive_write_header(writer.get(), entry);
134 if (result <= ARCHIVE_WARN) {
136 std::string(
"Failed to write archive header: ") +
137 archive_error_string(writer.get()));
140 if (archive_entry_size(entry) > 0) {
143 #if ARCHIVE_VERSION_NUMBER >= 3000000 151 result = archive_read_data_block(reader.get(), &buff, &
size, &offset);
152 if (result == ARCHIVE_EOF) {
154 }
else if (result <= ARCHIVE_WARN) {
156 std::string(
"Failed to read archive data block: ") +
157 archive_error_string(reader.get()));
160 result = archive_write_data_block(writer.get(), buff,
size, offset);
161 if (result <= ARCHIVE_WARN) {
163 std::string(
"Failed to write archive data block: ") +
164 archive_error_string(writer.get()));
169 result = archive_write_finish_entry(writer.get());
170 if (result <= ARCHIVE_WARN) {
172 std::string(
"Failed to write archive finish entry: ") +
173 archive_error_string(writer.get()));
182 #endif // __STOUT_ARCHIVER_HPP__ Definition: nothing.hpp:16
Definition: errorbase.hpp:36
Try< Bytes > size(const std::string &path, const FollowSymlink follow=FollowSymlink::FOLLOW_SYMLINK)
Definition: stat.hpp:130
Try< int_fd > open(const std::string &path, int oflag, mode_t mode=0)
Definition: open.hpp:35
std::string join(const std::string &path1, const std::string &path2, const char _separator=os::PATH_SEPARATOR)
Definition: path.hpp:116
constexpr int O_CLOEXEC
Definition: open.hpp:41
Try< Nothing > close(int fd)
Definition: close.hpp:24
#define flags
Definition: decoder.hpp:18
Try< Nothing > extract(const std::string &source, const std::string &destination, const int flags=ARCHIVE_EXTRACT_TIME|ARCHIVE_EXTRACT_SECURE_NODOTDOT)
Definition: archiver.hpp:40
Definition: archiver.hpp:31