rippled
Loading...
Searching...
No Matches
Archive.cpp
1#include <xrpl/basics/Archive.h>
2#include <xrpl/basics/contract.h>
3
4#include <boost/filesystem/operations.hpp>
5#include <boost/filesystem/path.hpp>
6
7#include <archive.h>
8#include <archive_entry.h>
9
10#include <cstddef>
11#include <memory>
12#include <stdexcept>
13
14namespace ripple {
15
16void
18 boost::filesystem::path const& src,
19 boost::filesystem::path const& dst)
20{
21 if (!is_regular_file(src))
22 Throw<std::runtime_error>("Invalid source file");
23
24 using archive_ptr =
25 std::unique_ptr<struct archive, void (*)(struct archive*)>;
26 archive_ptr ar{
27 archive_read_new(), [](struct archive* a) { archive_read_free(a); }};
28 if (!ar)
29 Throw<std::runtime_error>("Failed to allocate archive");
30
31 if (archive_read_support_format_tar(ar.get()) < ARCHIVE_OK)
32 Throw<std::runtime_error>(archive_error_string(ar.get()));
33
34 if (archive_read_support_filter_lz4(ar.get()) < ARCHIVE_OK)
35 Throw<std::runtime_error>(archive_error_string(ar.get()));
36
37 // Examples suggest this block size
38 if (archive_read_open_filename(ar.get(), src.string().c_str(), 10240) <
39 ARCHIVE_OK)
40 {
41 Throw<std::runtime_error>(archive_error_string(ar.get()));
42 }
43
44 archive_ptr aw{archive_write_disk_new(), [](struct archive* a) {
45 archive_write_free(a);
46 }};
47 if (!aw)
48 Throw<std::runtime_error>("Failed to allocate archive");
49
50 if (archive_write_disk_set_options(
51 aw.get(),
52 ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_ACL |
53 ARCHIVE_EXTRACT_FFLAGS) < ARCHIVE_OK)
54 {
55 Throw<std::runtime_error>(archive_error_string(aw.get()));
56 }
57
58 if (archive_write_disk_set_standard_lookup(aw.get()) < ARCHIVE_OK)
59 Throw<std::runtime_error>(archive_error_string(aw.get()));
60
61 int result;
62 struct archive_entry* entry;
63 while (true)
64 {
65 result = archive_read_next_header(ar.get(), &entry);
66 if (result == ARCHIVE_EOF)
67 break;
68 if (result < ARCHIVE_OK)
69 Throw<std::runtime_error>(archive_error_string(ar.get()));
70
71 archive_entry_set_pathname(
72 entry, (dst / archive_entry_pathname(entry)).string().c_str());
73 if (archive_write_header(aw.get(), entry) < ARCHIVE_OK)
74 Throw<std::runtime_error>(archive_error_string(aw.get()));
75
76 if (archive_entry_size(entry) > 0)
77 {
78 void const* buf;
79 size_t sz;
80 la_int64_t offset;
81 while (true)
82 {
83 result = archive_read_data_block(ar.get(), &buf, &sz, &offset);
84 if (result == ARCHIVE_EOF)
85 break;
86 if (result < ARCHIVE_OK)
87 Throw<std::runtime_error>(archive_error_string(ar.get()));
88
89 if (archive_write_data_block(aw.get(), buf, sz, offset) <
90 ARCHIVE_OK)
91 {
92 Throw<std::runtime_error>(archive_error_string(aw.get()));
93 }
94 }
95 }
96
97 if (archive_write_finish_entry(aw.get()) < ARCHIVE_OK)
98 Throw<std::runtime_error>(archive_error_string(aw.get()));
99 }
100}
101
102} // namespace ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
void extractTarLz4(boost::filesystem::path const &src, boost::filesystem::path const &dst)
Extract a tar archive compressed with lz4.
Definition Archive.cpp:17