summaryrefslogtreecommitdiff
path: root/Userland/Utilities/tar.cpp
diff options
context:
space:
mode:
authorTim Schumacher <timschumi@gmx.de>2022-03-04 20:42:27 +0100
committerAndreas Kling <kling@serenityos.org>2022-03-05 13:17:13 +0100
commit495a1be9258c00c37fb56169fb028c8b2ea38478 (patch)
treee3ee6678abd28f458fbc26a4d799d956e780324f /Userland/Utilities/tar.cpp
parentf6e86915f549706c8a60056eb464f8c85dcb857e (diff)
downloadserenity-495a1be9258c00c37fb56169fb028c8b2ea38478.zip
tar: Implement support for extended headers :^)
Diffstat (limited to 'Userland/Utilities/tar.cpp')
-rw-r--r--Userland/Utilities/tar.cpp57
1 files changed, 48 insertions, 9 deletions
diff --git a/Userland/Utilities/tar.cpp b/Userland/Utilities/tar.cpp
index 763dc1b1eb..e2d02c8933 100644
--- a/Userland/Utilities/tar.cpp
+++ b/Userland/Utilities/tar.cpp
@@ -77,13 +77,57 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
warnln("the provided file is not a well-formatted ustar file");
return 1;
}
+
+ HashMap<String, String> global_overrides;
+ HashMap<String, String> local_overrides;
+
+ auto get_override = [&](StringView key) -> Optional<String> {
+ Optional<String> maybe_local = local_overrides.get(key);
+
+ if (maybe_local.has_value())
+ return maybe_local;
+
+ Optional<String> maybe_global = global_overrides.get(key);
+
+ if (maybe_global.has_value())
+ return maybe_global;
+
+ return {};
+ };
+
for (; !tar_stream.finished(); tar_stream.advance()) {
const Archive::TarFileHeader& header = tar_stream.header();
+ // Handle meta-entries earlier to avoid consuming the file content stream.
+ if (header.content_is_like_extended_header()) {
+ switch (header.type_flag()) {
+ case Archive::TarFileType::GlobalExtendedHeader: {
+ TRY(tar_stream.for_each_extended_header([&](StringView key, StringView value) {
+ if (value.length() == 0)
+ global_overrides.remove(key);
+ else
+ global_overrides.set(key, value);
+ }));
+ break;
+ }
+ case Archive::TarFileType::ExtendedHeader: {
+ TRY(tar_stream.for_each_extended_header([&](StringView key, StringView value) {
+ local_overrides.set(key, value);
+ }));
+ break;
+ }
+ default:
+ warnln("Unknown extended header type '{}' of {}", (char)header.type_flag(), header.filename());
+ VERIFY_NOT_REACHED();
+ }
+
+ continue;
+ }
+
LexicalPath path = LexicalPath(header.filename());
if (!header.prefix().is_empty())
path = path.prepend(header.prefix());
- String filename = path.string();
+ String filename = get_override("path"sv).value_or(path.string());
if (list || verbose)
outln("{}", filename);
@@ -122,20 +166,15 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
return result_or_error.error();
break;
}
- case Archive::TarFileType::GlobalExtendedHeader: {
- dbgln("ignoring global extended header: {}", header.filename());
- break;
- }
- case Archive::TarFileType::ExtendedHeader: {
- dbgln("ignoring extended header: {}", header.filename());
- break;
- }
default:
// FIXME: Implement other file types
warnln("file type '{}' of {} is not yet supported", (char)header.type_flag(), header.filename());
VERIFY_NOT_REACHED();
}
}
+
+ // Non-global headers should be cleared after every file.
+ local_overrides.clear();
}
file_stream.close();