archive_r_ruby 0.1.21 → 0.1.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +21 -21
  3. data/NOTICE +116 -116
  4. data/README.md +106 -106
  5. data/VERSION +1 -1
  6. data/ext/archive_r/archive_r_ext.cc +1098 -1098
  7. data/ext/archive_r/extconf.rb +125 -125
  8. data/ext/archive_r/vendor/archive_r/LICENSE +21 -21
  9. data/ext/archive_r/vendor/archive_r/NOTICE +116 -116
  10. data/ext/archive_r/vendor/archive_r/include/archive_r/data_stream.h +42 -42
  11. data/ext/archive_r/vendor/archive_r/include/archive_r/entry.h +180 -180
  12. data/ext/archive_r/vendor/archive_r/include/archive_r/entry_fault.h +34 -34
  13. data/ext/archive_r/vendor/archive_r/include/archive_r/entry_metadata.h +56 -56
  14. data/ext/archive_r/vendor/archive_r/include/archive_r/multi_volume_stream_base.h +46 -46
  15. data/ext/archive_r/vendor/archive_r/include/archive_r/path_hierarchy.h +92 -92
  16. data/ext/archive_r/vendor/archive_r/include/archive_r/path_hierarchy_utils.h +36 -36
  17. data/ext/archive_r/vendor/archive_r/include/archive_r/platform_compat.h +34 -34
  18. data/ext/archive_r/vendor/archive_r/include/archive_r/traverser.h +156 -156
  19. data/ext/archive_r/vendor/archive_r/src/archive_stack_cursor.cc +300 -300
  20. data/ext/archive_r/vendor/archive_r/src/archive_stack_cursor.h +110 -110
  21. data/ext/archive_r/vendor/archive_r/src/archive_stack_orchestrator.cc +161 -161
  22. data/ext/archive_r/vendor/archive_r/src/archive_stack_orchestrator.h +53 -53
  23. data/ext/archive_r/vendor/archive_r/src/archive_type.cc +545 -545
  24. data/ext/archive_r/vendor/archive_r/src/archive_type.h +77 -77
  25. data/ext/archive_r/vendor/archive_r/src/data_stream.cc +35 -35
  26. data/ext/archive_r/vendor/archive_r/src/entry.cc +238 -238
  27. data/ext/archive_r/vendor/archive_r/src/entry_fault.cc +26 -26
  28. data/ext/archive_r/vendor/archive_r/src/entry_fault_error.cc +54 -54
  29. data/ext/archive_r/vendor/archive_r/src/entry_fault_error.h +32 -32
  30. data/ext/archive_r/vendor/archive_r/src/entry_impl.h +56 -56
  31. data/ext/archive_r/vendor/archive_r/src/multi_volume_manager.cc +76 -76
  32. data/ext/archive_r/vendor/archive_r/src/multi_volume_manager.h +39 -39
  33. data/ext/archive_r/vendor/archive_r/src/multi_volume_stream_base.cc +208 -208
  34. data/ext/archive_r/vendor/archive_r/src/path_hierarchy.cc +127 -127
  35. data/ext/archive_r/vendor/archive_r/src/path_hierarchy_utils.cc +251 -251
  36. data/ext/archive_r/vendor/archive_r/src/simple_profiler.h +109 -109
  37. data/ext/archive_r/vendor/archive_r/src/system_file_stream.cc +294 -294
  38. data/ext/archive_r/vendor/archive_r/src/system_file_stream.h +46 -46
  39. data/ext/archive_r/vendor/archive_r/src/traverser.cc +295 -295
  40. data/lib/archive_r.rb +120 -120
  41. metadata +3 -6
@@ -1,238 +1,238 @@
1
- // SPDX-License-Identifier: MIT
2
- // Copyright (c) 2025 archive_r Team
3
-
4
- #include "archive_r/entry.h"
5
- #include "archive_r/path_hierarchy_utils.h"
6
- #include "archive_stack_orchestrator.h"
7
- #include "entry_fault_error.h"
8
- #include "entry_impl.h"
9
- #include "system_file_stream.h"
10
- #include <archive.h>
11
- #include <archive_entry.h>
12
- #include <filesystem>
13
- #include <sstream>
14
- #include <sys/stat.h>
15
- #include <system_error>
16
- #include <unordered_set>
17
- #include <utility>
18
-
19
- namespace archive_r {
20
-
21
- // ============================================================================
22
- // Entry::Impl Implementation
23
- // ============================================================================
24
-
25
- // Unified constructor - receives metadata directly
26
- // Copy constructor - cached orchestrator is NOT copied (will be recreated on first read)
27
- Entry::Impl::Impl(const Impl &other)
28
- : _path_hierarchy(other._path_hierarchy)
29
- , _size(other._size)
30
- , _filetype(other._filetype)
31
- , _metadata(other._metadata)
32
- , _descend_enabled(other._descend_enabled)
33
- , _orchestrator(nullptr)
34
- , _shares_traverser_orchestrator(false)
35
- , _archive_options(other._archive_options) {}
36
-
37
- // Copy assignment operator
38
- Entry::Impl::Impl(const PathHierarchy &hierarchy, std::shared_ptr<ArchiveStackOrchestrator> data_source_orchestrator, bool default_descent)
39
- : _path_hierarchy(hierarchy)
40
- , _size(0)
41
- , _filetype(0)
42
- , _descend_enabled(default_descent)
43
- , _orchestrator(std::move(data_source_orchestrator))
44
- , _shares_traverser_orchestrator(static_cast<bool>(_orchestrator)) {
45
- if (!_orchestrator) {
46
- return;
47
- }
48
-
49
- const auto &keys = _orchestrator->metadata_keys();
50
-
51
- const StreamArchive *archive = _orchestrator->current_archive();
52
- const bool use_archive_metadata = archive && _path_hierarchy.size() > 1;
53
-
54
- if (use_archive_metadata) {
55
- _size = archive->current_entry_size();
56
- _filetype = archive->current_entry_filetype();
57
- if (!keys.empty()) {
58
- _metadata = archive->current_entry_metadata(keys);
59
- }
60
- } else if (!hierarchy.empty()) {
61
- FilesystemMetadataInfo info = collect_root_path_metadata(hierarchy, keys);
62
- _size = info.size;
63
- _filetype = info.filetype;
64
- _metadata = std::move(info.metadata);
65
- }
66
-
67
- if (use_archive_metadata) {
68
- _archive_options = _orchestrator->options();
69
- } else {
70
- _archive_options.reset();
71
- }
72
-
73
- if (_filetype == 0 && archive && _orchestrator->depth() == _path_hierarchy.size()) {
74
- _filetype = AE_IFREG;
75
- }
76
- }
77
-
78
- std::string Entry::Impl::name() const {
79
- if (_path_hierarchy.empty()) {
80
- return "";
81
- }
82
- const PathEntry &tail = _path_hierarchy.back();
83
- std::string display_name;
84
- if (entry_name_from_component(tail, display_name) && !display_name.empty()) {
85
- return display_name;
86
- }
87
- if (tail.is_single()) {
88
- return tail.single_value();
89
- }
90
- return path_entry_display(tail);
91
- }
92
-
93
- const PathHierarchy &Entry::Impl::path_hierarchy() const { return _path_hierarchy; }
94
-
95
- bool Entry::Impl::is_directory() const { return _filetype == AE_IFDIR; }
96
-
97
- bool Entry::Impl::is_file() const { return _filetype == AE_IFREG; }
98
-
99
- uint64_t Entry::Impl::size() const { return _size; }
100
-
101
- size_t Entry::Impl::depth() const {
102
- // Depth is based on path hierarchy length
103
- return _path_hierarchy.size() > 0 ? _path_hierarchy.size() - 1 : 0;
104
- }
105
-
106
- void Entry::Impl::set_descent(bool enabled) {
107
- if (!_shares_traverser_orchestrator) {
108
- emit_fault("set_descent requires traverser-managed orchestrator");
109
- return;
110
- }
111
- _descend_enabled = enabled;
112
- }
113
-
114
- bool Entry::Impl::descent_enabled() const { return _descend_enabled; }
115
-
116
- const EntryMetadataMap &Entry::Impl::metadata() const { return _metadata; }
117
-
118
- const EntryMetadataValue *Entry::Impl::metadata_value(const std::string &key) const {
119
- const auto it = _metadata.find(key);
120
- if (it == _metadata.end()) {
121
- return nullptr;
122
- }
123
- return &it->second;
124
- }
125
-
126
- void Entry::Impl::set_multi_volume_group(const std::string &base_name, const MultiVolumeGroupOptions &options) {
127
- if (!_shares_traverser_orchestrator) {
128
- emit_fault("set_multi_volume_group requires traverser-managed orchestrator");
129
- return;
130
- }
131
-
132
- // Notify traverser via ArchiveStackOrchestrator
133
- _descend_enabled = false;
134
- _orchestrator->mark_entry_as_multi_volume(_path_hierarchy, base_name, options.ordering);
135
- }
136
-
137
- void Entry::Impl::emit_fault(const std::string &message, int errno_value) const {
138
- EntryFault fault;
139
- fault.message = message;
140
- fault.errno_value = errno_value;
141
- fault.hierarchy = _path_hierarchy;
142
- dispatch_registered_fault(fault);
143
- }
144
-
145
- std::shared_ptr<ArchiveStackOrchestrator> Entry::Impl::ensure_orchestrator() {
146
- if (_orchestrator) {
147
- if (_shares_traverser_orchestrator && _orchestrator->depth() == 0) {
148
- // Traverser-managed orchestrator never synchronized to this entry (depth 0 filesystem read).
149
- _orchestrator.reset();
150
- _shares_traverser_orchestrator = false;
151
- } else {
152
- return _orchestrator;
153
- }
154
- }
155
-
156
- ArchiveOption opts = _archive_options.value_or(ArchiveOption{});
157
- _orchestrator = std::make_shared<ArchiveStackOrchestrator>(opts);
158
- if (!_orchestrator->synchronize_to_hierarchy(_path_hierarchy)) {
159
- _orchestrator.reset();
160
- return nullptr;
161
- }
162
- _shares_traverser_orchestrator = false;
163
- return _orchestrator;
164
- }
165
-
166
- ssize_t Entry::Impl::read(void *buffer, size_t length) {
167
- if (!ensure_orchestrator()) {
168
- emit_fault("Failed to initialize ArchiveStackOrchestrator");
169
- return -1;
170
- }
171
- const ssize_t bytes_read = _orchestrator->read_head(buffer, length);
172
- if (bytes_read < 0) {
173
- emit_fault("Failed to read entry content");
174
- return -1;
175
- }
176
-
177
- _descend_enabled = false; // Require explicit re-enable before descending again
178
-
179
- return bytes_read;
180
- }
181
-
182
- // ============================================================================
183
- // Entry Public API Implementation
184
- // ============================================================================
185
-
186
- Entry::Entry(const PathHierarchy &hierarchy, std::shared_ptr<ArchiveStackOrchestrator> data_source_orchestrator, bool default_descent)
187
- : _impl(std::make_unique<Impl>(hierarchy, std::move(data_source_orchestrator), default_descent)) {}
188
-
189
- Entry::Entry(Impl *impl)
190
- : _impl(impl) {}
191
-
192
- Entry::~Entry() = default;
193
-
194
- std::unique_ptr<Entry> Entry::create(PathHierarchy hierarchy, std::shared_ptr<ArchiveStackOrchestrator> data_source_orchestrator, bool default_descent) {
195
- return std::unique_ptr<Entry>(new Entry(hierarchy, std::move(data_source_orchestrator), default_descent));
196
- }
197
-
198
- // Copy operations - creates a new Impl copy
199
- Entry::Entry(const Entry &other)
200
- : _impl(other._impl ? std::make_unique<Impl>(*other._impl) : nullptr) {}
201
-
202
- Entry &Entry::operator=(const Entry &other) {
203
- if (this != &other) {
204
- _impl = other._impl ? std::make_unique<Impl>(*other._impl) : nullptr;
205
- }
206
- return *this;
207
- }
208
-
209
- Entry::Entry(Entry &&) noexcept = default;
210
- Entry &Entry::operator=(Entry &&) noexcept = default;
211
-
212
- std::string Entry::name() const { return _impl->name(); }
213
-
214
- std::string Entry::path() const { return hierarchy_display(_impl->path_hierarchy()); }
215
-
216
- const PathHierarchy &Entry::path_hierarchy() const { return _impl->path_hierarchy(); }
217
-
218
- bool Entry::is_directory() const { return _impl->is_directory(); }
219
-
220
- bool Entry::is_file() const { return _impl->is_file(); }
221
-
222
- uint64_t Entry::size() const { return _impl->size(); }
223
-
224
- size_t Entry::depth() const { return _impl->depth(); }
225
-
226
- ssize_t Entry::read(void *buffer, size_t length) { return _impl->read(buffer, length); }
227
-
228
- void Entry::set_descent(bool enabled) { _impl->set_descent(enabled); }
229
-
230
- bool Entry::descent_enabled() const { return _impl->descent_enabled(); }
231
-
232
- void Entry::set_multi_volume_group(const std::string &base_name, const MultiVolumeGroupOptions &options) { _impl->set_multi_volume_group(base_name, options); }
233
-
234
- const EntryMetadataMap &Entry::metadata() const { return _impl->metadata(); }
235
-
236
- const EntryMetadataValue *Entry::find_metadata(const std::string &key) const { return _impl->metadata_value(key); }
237
-
238
- } // namespace archive_r
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2025 archive_r Team
3
+
4
+ #include "archive_r/entry.h"
5
+ #include "archive_r/path_hierarchy_utils.h"
6
+ #include "archive_stack_orchestrator.h"
7
+ #include "entry_fault_error.h"
8
+ #include "entry_impl.h"
9
+ #include "system_file_stream.h"
10
+ #include <archive.h>
11
+ #include <archive_entry.h>
12
+ #include <filesystem>
13
+ #include <sstream>
14
+ #include <sys/stat.h>
15
+ #include <system_error>
16
+ #include <unordered_set>
17
+ #include <utility>
18
+
19
+ namespace archive_r {
20
+
21
+ // ============================================================================
22
+ // Entry::Impl Implementation
23
+ // ============================================================================
24
+
25
+ // Unified constructor - receives metadata directly
26
+ // Copy constructor - cached orchestrator is NOT copied (will be recreated on first read)
27
+ Entry::Impl::Impl(const Impl &other)
28
+ : _path_hierarchy(other._path_hierarchy)
29
+ , _size(other._size)
30
+ , _filetype(other._filetype)
31
+ , _metadata(other._metadata)
32
+ , _descend_enabled(other._descend_enabled)
33
+ , _orchestrator(nullptr)
34
+ , _shares_traverser_orchestrator(false)
35
+ , _archive_options(other._archive_options) {}
36
+
37
+ // Copy assignment operator
38
+ Entry::Impl::Impl(const PathHierarchy &hierarchy, std::shared_ptr<ArchiveStackOrchestrator> data_source_orchestrator, bool default_descent)
39
+ : _path_hierarchy(hierarchy)
40
+ , _size(0)
41
+ , _filetype(0)
42
+ , _descend_enabled(default_descent)
43
+ , _orchestrator(std::move(data_source_orchestrator))
44
+ , _shares_traverser_orchestrator(static_cast<bool>(_orchestrator)) {
45
+ if (!_orchestrator) {
46
+ return;
47
+ }
48
+
49
+ const auto &keys = _orchestrator->metadata_keys();
50
+
51
+ const StreamArchive *archive = _orchestrator->current_archive();
52
+ const bool use_archive_metadata = archive && _path_hierarchy.size() > 1;
53
+
54
+ if (use_archive_metadata) {
55
+ _size = archive->current_entry_size();
56
+ _filetype = archive->current_entry_filetype();
57
+ if (!keys.empty()) {
58
+ _metadata = archive->current_entry_metadata(keys);
59
+ }
60
+ } else if (!hierarchy.empty()) {
61
+ FilesystemMetadataInfo info = collect_root_path_metadata(hierarchy, keys);
62
+ _size = info.size;
63
+ _filetype = info.filetype;
64
+ _metadata = std::move(info.metadata);
65
+ }
66
+
67
+ if (use_archive_metadata) {
68
+ _archive_options = _orchestrator->options();
69
+ } else {
70
+ _archive_options.reset();
71
+ }
72
+
73
+ if (_filetype == 0 && archive && _orchestrator->depth() == _path_hierarchy.size()) {
74
+ _filetype = AE_IFREG;
75
+ }
76
+ }
77
+
78
+ std::string Entry::Impl::name() const {
79
+ if (_path_hierarchy.empty()) {
80
+ return "";
81
+ }
82
+ const PathEntry &tail = _path_hierarchy.back();
83
+ std::string display_name;
84
+ if (entry_name_from_component(tail, display_name) && !display_name.empty()) {
85
+ return display_name;
86
+ }
87
+ if (tail.is_single()) {
88
+ return tail.single_value();
89
+ }
90
+ return path_entry_display(tail);
91
+ }
92
+
93
+ const PathHierarchy &Entry::Impl::path_hierarchy() const { return _path_hierarchy; }
94
+
95
+ bool Entry::Impl::is_directory() const { return _filetype == AE_IFDIR; }
96
+
97
+ bool Entry::Impl::is_file() const { return _filetype == AE_IFREG; }
98
+
99
+ uint64_t Entry::Impl::size() const { return _size; }
100
+
101
+ size_t Entry::Impl::depth() const {
102
+ // Depth is based on path hierarchy length
103
+ return _path_hierarchy.size() > 0 ? _path_hierarchy.size() - 1 : 0;
104
+ }
105
+
106
+ void Entry::Impl::set_descent(bool enabled) {
107
+ if (!_shares_traverser_orchestrator) {
108
+ emit_fault("set_descent requires traverser-managed orchestrator");
109
+ return;
110
+ }
111
+ _descend_enabled = enabled;
112
+ }
113
+
114
+ bool Entry::Impl::descent_enabled() const { return _descend_enabled; }
115
+
116
+ const EntryMetadataMap &Entry::Impl::metadata() const { return _metadata; }
117
+
118
+ const EntryMetadataValue *Entry::Impl::metadata_value(const std::string &key) const {
119
+ const auto it = _metadata.find(key);
120
+ if (it == _metadata.end()) {
121
+ return nullptr;
122
+ }
123
+ return &it->second;
124
+ }
125
+
126
+ void Entry::Impl::set_multi_volume_group(const std::string &base_name, const MultiVolumeGroupOptions &options) {
127
+ if (!_shares_traverser_orchestrator) {
128
+ emit_fault("set_multi_volume_group requires traverser-managed orchestrator");
129
+ return;
130
+ }
131
+
132
+ // Notify traverser via ArchiveStackOrchestrator
133
+ _descend_enabled = false;
134
+ _orchestrator->mark_entry_as_multi_volume(_path_hierarchy, base_name, options.ordering);
135
+ }
136
+
137
+ void Entry::Impl::emit_fault(const std::string &message, int errno_value) const {
138
+ EntryFault fault;
139
+ fault.message = message;
140
+ fault.errno_value = errno_value;
141
+ fault.hierarchy = _path_hierarchy;
142
+ dispatch_registered_fault(fault);
143
+ }
144
+
145
+ std::shared_ptr<ArchiveStackOrchestrator> Entry::Impl::ensure_orchestrator() {
146
+ if (_orchestrator) {
147
+ if (_shares_traverser_orchestrator && _orchestrator->depth() == 0) {
148
+ // Traverser-managed orchestrator never synchronized to this entry (depth 0 filesystem read).
149
+ _orchestrator.reset();
150
+ _shares_traverser_orchestrator = false;
151
+ } else {
152
+ return _orchestrator;
153
+ }
154
+ }
155
+
156
+ ArchiveOption opts = _archive_options.value_or(ArchiveOption{});
157
+ _orchestrator = std::make_shared<ArchiveStackOrchestrator>(opts);
158
+ if (!_orchestrator->synchronize_to_hierarchy(_path_hierarchy)) {
159
+ _orchestrator.reset();
160
+ return nullptr;
161
+ }
162
+ _shares_traverser_orchestrator = false;
163
+ return _orchestrator;
164
+ }
165
+
166
+ ssize_t Entry::Impl::read(void *buffer, size_t length) {
167
+ if (!ensure_orchestrator()) {
168
+ emit_fault("Failed to initialize ArchiveStackOrchestrator");
169
+ return -1;
170
+ }
171
+ const ssize_t bytes_read = _orchestrator->read_head(buffer, length);
172
+ if (bytes_read < 0) {
173
+ emit_fault("Failed to read entry content");
174
+ return -1;
175
+ }
176
+
177
+ _descend_enabled = false; // Require explicit re-enable before descending again
178
+
179
+ return bytes_read;
180
+ }
181
+
182
+ // ============================================================================
183
+ // Entry Public API Implementation
184
+ // ============================================================================
185
+
186
+ Entry::Entry(const PathHierarchy &hierarchy, std::shared_ptr<ArchiveStackOrchestrator> data_source_orchestrator, bool default_descent)
187
+ : _impl(std::make_unique<Impl>(hierarchy, std::move(data_source_orchestrator), default_descent)) {}
188
+
189
+ Entry::Entry(Impl *impl)
190
+ : _impl(impl) {}
191
+
192
+ Entry::~Entry() = default;
193
+
194
+ std::unique_ptr<Entry> Entry::create(PathHierarchy hierarchy, std::shared_ptr<ArchiveStackOrchestrator> data_source_orchestrator, bool default_descent) {
195
+ return std::unique_ptr<Entry>(new Entry(hierarchy, std::move(data_source_orchestrator), default_descent));
196
+ }
197
+
198
+ // Copy operations - creates a new Impl copy
199
+ Entry::Entry(const Entry &other)
200
+ : _impl(other._impl ? std::make_unique<Impl>(*other._impl) : nullptr) {}
201
+
202
+ Entry &Entry::operator=(const Entry &other) {
203
+ if (this != &other) {
204
+ _impl = other._impl ? std::make_unique<Impl>(*other._impl) : nullptr;
205
+ }
206
+ return *this;
207
+ }
208
+
209
+ Entry::Entry(Entry &&) noexcept = default;
210
+ Entry &Entry::operator=(Entry &&) noexcept = default;
211
+
212
+ std::string Entry::name() const { return _impl->name(); }
213
+
214
+ std::string Entry::path() const { return hierarchy_display(_impl->path_hierarchy()); }
215
+
216
+ const PathHierarchy &Entry::path_hierarchy() const { return _impl->path_hierarchy(); }
217
+
218
+ bool Entry::is_directory() const { return _impl->is_directory(); }
219
+
220
+ bool Entry::is_file() const { return _impl->is_file(); }
221
+
222
+ uint64_t Entry::size() const { return _impl->size(); }
223
+
224
+ size_t Entry::depth() const { return _impl->depth(); }
225
+
226
+ ssize_t Entry::read(void *buffer, size_t length) { return _impl->read(buffer, length); }
227
+
228
+ void Entry::set_descent(bool enabled) { _impl->set_descent(enabled); }
229
+
230
+ bool Entry::descent_enabled() const { return _impl->descent_enabled(); }
231
+
232
+ void Entry::set_multi_volume_group(const std::string &base_name, const MultiVolumeGroupOptions &options) { _impl->set_multi_volume_group(base_name, options); }
233
+
234
+ const EntryMetadataMap &Entry::metadata() const { return _impl->metadata(); }
235
+
236
+ const EntryMetadataValue *Entry::find_metadata(const std::string &key) const { return _impl->metadata_value(key); }
237
+
238
+ } // namespace archive_r
@@ -1,26 +1,26 @@
1
- // SPDX-License-Identifier: MIT
2
- // Copyright (c) 2025 archive_r Team
3
-
4
- #include "archive_r/entry_fault.h"
5
-
6
- #include <atomic>
7
- #include <memory>
8
-
9
- namespace archive_r {
10
- namespace {
11
- std::shared_ptr<const FaultCallback> g_fault_callback = std::make_shared<const FaultCallback>();
12
- }
13
-
14
- void register_fault_callback(FaultCallback callback) {
15
- auto new_callback = std::make_shared<const FaultCallback>(std::move(callback));
16
- std::atomic_store_explicit(&g_fault_callback, std::move(new_callback), std::memory_order_release);
17
- }
18
-
19
- void dispatch_registered_fault(const EntryFault &fault) {
20
- auto callback = std::atomic_load_explicit(&g_fault_callback, std::memory_order_acquire);
21
- if (callback && *callback) {
22
- (*callback)(fault);
23
- }
24
- }
25
-
26
- } // namespace archive_r
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2025 archive_r Team
3
+
4
+ #include "archive_r/entry_fault.h"
5
+
6
+ #include <atomic>
7
+ #include <memory>
8
+
9
+ namespace archive_r {
10
+ namespace {
11
+ std::shared_ptr<const FaultCallback> g_fault_callback = std::make_shared<const FaultCallback>();
12
+ }
13
+
14
+ void register_fault_callback(FaultCallback callback) {
15
+ auto new_callback = std::make_shared<const FaultCallback>(std::move(callback));
16
+ std::atomic_store_explicit(&g_fault_callback, std::move(new_callback), std::memory_order_release);
17
+ }
18
+
19
+ void dispatch_registered_fault(const EntryFault &fault) {
20
+ auto callback = std::atomic_load_explicit(&g_fault_callback, std::memory_order_acquire);
21
+ if (callback && *callback) {
22
+ (*callback)(fault);
23
+ }
24
+ }
25
+
26
+ } // namespace archive_r
@@ -1,54 +1,54 @@
1
- // SPDX-License-Identifier: MIT
2
- // Copyright (c) 2025 archive_r Team
3
-
4
- #include "entry_fault_error.h"
5
-
6
- #include <cstring>
7
- #include <string>
8
- #include <utility>
9
-
10
- namespace archive_r {
11
-
12
- EntryFaultError::EntryFaultError(EntryFault fault)
13
- : std::runtime_error(fault.message)
14
- , _fault(std::move(fault)) {}
15
-
16
- EntryFaultError::EntryFaultError(EntryFault fault, const std::string &internal_message)
17
- : std::runtime_error(internal_message.empty() ? fault.message : internal_message)
18
- , _fault(std::move(fault)) {}
19
-
20
- EntryFaultError make_entry_fault_error(const std::string &message, PathHierarchy hierarchy, int errno_value) {
21
- EntryFault fault;
22
- fault.hierarchy = std::move(hierarchy);
23
- fault.message = message;
24
- fault.errno_value = errno_value;
25
- return EntryFaultError(std::move(fault));
26
- }
27
-
28
- std::string format_errno_error(const std::string &prefix, int err) {
29
- if (err == 0) {
30
- return prefix;
31
- }
32
-
33
- std::string message = prefix;
34
- message.append(": ");
35
- message.append(std::strerror(err));
36
- message.append(" (posix errno=");
37
- message.append(std::to_string(err));
38
- message.push_back(')');
39
- return message;
40
- }
41
-
42
- std::string format_path_errno_error(const std::string &action, const std::string &path, int err) {
43
- std::string prefix = action;
44
- if (!path.empty()) {
45
- prefix.append(" '");
46
- prefix.append(path);
47
- prefix.push_back('\'');
48
- }
49
- return format_errno_error(prefix, err);
50
- }
51
-
52
- std::string prefer_error_detail(const std::string &detail, const std::string &fallback) { return detail.empty() ? fallback : detail; }
53
-
54
- } // namespace archive_r
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2025 archive_r Team
3
+
4
+ #include "entry_fault_error.h"
5
+
6
+ #include <cstring>
7
+ #include <string>
8
+ #include <utility>
9
+
10
+ namespace archive_r {
11
+
12
+ EntryFaultError::EntryFaultError(EntryFault fault)
13
+ : std::runtime_error(fault.message)
14
+ , _fault(std::move(fault)) {}
15
+
16
+ EntryFaultError::EntryFaultError(EntryFault fault, const std::string &internal_message)
17
+ : std::runtime_error(internal_message.empty() ? fault.message : internal_message)
18
+ , _fault(std::move(fault)) {}
19
+
20
+ EntryFaultError make_entry_fault_error(const std::string &message, PathHierarchy hierarchy, int errno_value) {
21
+ EntryFault fault;
22
+ fault.hierarchy = std::move(hierarchy);
23
+ fault.message = message;
24
+ fault.errno_value = errno_value;
25
+ return EntryFaultError(std::move(fault));
26
+ }
27
+
28
+ std::string format_errno_error(const std::string &prefix, int err) {
29
+ if (err == 0) {
30
+ return prefix;
31
+ }
32
+
33
+ std::string message = prefix;
34
+ message.append(": ");
35
+ message.append(std::strerror(err));
36
+ message.append(" (posix errno=");
37
+ message.append(std::to_string(err));
38
+ message.push_back(')');
39
+ return message;
40
+ }
41
+
42
+ std::string format_path_errno_error(const std::string &action, const std::string &path, int err) {
43
+ std::string prefix = action;
44
+ if (!path.empty()) {
45
+ prefix.append(" '");
46
+ prefix.append(path);
47
+ prefix.push_back('\'');
48
+ }
49
+ return format_errno_error(prefix, err);
50
+ }
51
+
52
+ std::string prefer_error_detail(const std::string &detail, const std::string &fallback) { return detail.empty() ? fallback : detail; }
53
+
54
+ } // namespace archive_r