tar: Implement support for extended headers :^)

This commit is contained in:
Tim Schumacher 2022-03-04 20:42:27 +01:00 committed by Andreas Kling
parent f6e86915f5
commit 495a1be925
Notes: sideshowbarker 2024-07-17 23:07:41 +09:00

View file

@ -77,13 +77,57 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
warnln("the provided file is not a well-formatted ustar file"); warnln("the provided file is not a well-formatted ustar file");
return 1; 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()) { for (; !tar_stream.finished(); tar_stream.advance()) {
const Archive::TarFileHeader& header = tar_stream.header(); 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()); LexicalPath path = LexicalPath(header.filename());
if (!header.prefix().is_empty()) if (!header.prefix().is_empty())
path = path.prepend(header.prefix()); path = path.prepend(header.prefix());
String filename = path.string(); String filename = get_override("path"sv).value_or(path.string());
if (list || verbose) if (list || verbose)
outln("{}", filename); outln("{}", filename);
@ -122,20 +166,15 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
return result_or_error.error(); return result_or_error.error();
break; 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: default:
// FIXME: Implement other file types // FIXME: Implement other file types
warnln("file type '{}' of {} is not yet supported", (char)header.type_flag(), header.filename()); warnln("file type '{}' of {} is not yet supported", (char)header.type_flag(), header.filename());
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
} }
} }
// Non-global headers should be cleared after every file.
local_overrides.clear();
} }
file_stream.close(); file_stream.close();