|
@@ -15,6 +15,7 @@
|
|
#include <LibCore/DirIterator.h>
|
|
#include <LibCore/DirIterator.h>
|
|
#include <LibCore/File.h>
|
|
#include <LibCore/File.h>
|
|
#include <LibCore/FileStream.h>
|
|
#include <LibCore/FileStream.h>
|
|
|
|
+#include <LibCore/Stream.h>
|
|
#include <LibCore/System.h>
|
|
#include <LibCore/System.h>
|
|
#include <LibMain/Main.h>
|
|
#include <LibMain/Main.h>
|
|
#include <fcntl.h>
|
|
#include <fcntl.h>
|
|
@@ -61,22 +62,34 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|
}
|
|
}
|
|
|
|
|
|
if (list || extract) {
|
|
if (list || extract) {
|
|
- auto file = Core::File::standard_input();
|
|
|
|
-
|
|
|
|
- if (!archive_file.is_empty())
|
|
|
|
- file = TRY(Core::File::open(archive_file, Core::OpenMode::ReadOnly));
|
|
|
|
-
|
|
|
|
if (!directory.is_empty())
|
|
if (!directory.is_empty())
|
|
TRY(Core::System::chdir(directory));
|
|
TRY(Core::System::chdir(directory));
|
|
|
|
|
|
- Core::InputFileStream file_stream(file);
|
|
|
|
- Compress::GzipDecompressor gzip_stream(file_stream);
|
|
|
|
|
|
+ // FIXME: Remove these once we have smart pointers everywhere in LibArchive and LibCompress (or just ported the whole stack to Core::Stream).
|
|
|
|
+ // Until then, we have to hold on to _some_ instance of the file AK::Stream.
|
|
|
|
+ // Note that this is only in use together with gzip.
|
|
|
|
+ OwnPtr<Core::InputFileStream> file_stream;
|
|
|
|
+
|
|
|
|
+ auto input_stream = TRY([&]() -> ErrorOr<NonnullOwnPtr<Core::Stream::Stream>> {
|
|
|
|
+ if (gzip) {
|
|
|
|
+ // FIXME: Port gzip to Core::Stream.
|
|
|
|
+ auto file = Core::File::standard_input();
|
|
|
|
+
|
|
|
|
+ if (!archive_file.is_empty())
|
|
|
|
+ file = TRY(Core::File::open(archive_file, Core::OpenMode::ReadOnly));
|
|
|
|
+
|
|
|
|
+ file_stream = adopt_own(*new Core::InputFileStream(file));
|
|
|
|
+ NonnullOwnPtr<InputStream> gzip_stream = make<Compress::GzipDecompressor>(*file_stream);
|
|
|
|
+
|
|
|
|
+ return make<Core::Stream::WrappedAKInputStream>(move(gzip_stream));
|
|
|
|
+ } else {
|
|
|
|
+ return TRY(Core::Stream::File::open_file_or_standard_stream(archive_file, Core::Stream::OpenMode::Read));
|
|
|
|
+ }
|
|
|
|
+ }());
|
|
|
|
|
|
- InputStream& file_input_stream = file_stream;
|
|
|
|
- InputStream& gzip_input_stream = gzip_stream;
|
|
|
|
- Archive::TarInputStream tar_stream((gzip) ? gzip_input_stream : file_input_stream);
|
|
|
|
|
|
+ auto tar_stream = TRY(Archive::TarInputStream::construct(move(input_stream)));
|
|
// FIXME: implement ErrorOr<TarInputStream>?
|
|
// FIXME: implement ErrorOr<TarInputStream>?
|
|
- if (!tar_stream.valid()) {
|
|
|
|
|
|
+ if (!tar_stream->valid()) {
|
|
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;
|
|
}
|
|
}
|
|
@@ -98,14 +111,14 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|
return {};
|
|
return {};
|
|
};
|
|
};
|
|
|
|
|
|
- while (!tar_stream.finished()) {
|
|
|
|
- Archive::TarFileHeader const& header = tar_stream.header();
|
|
|
|
|
|
+ while (!tar_stream->finished()) {
|
|
|
|
+ Archive::TarFileHeader const& header = tar_stream->header();
|
|
|
|
|
|
// Handle meta-entries earlier to avoid consuming the file content stream.
|
|
// Handle meta-entries earlier to avoid consuming the file content stream.
|
|
if (header.content_is_like_extended_header()) {
|
|
if (header.content_is_like_extended_header()) {
|
|
switch (header.type_flag()) {
|
|
switch (header.type_flag()) {
|
|
case Archive::TarFileType::GlobalExtendedHeader: {
|
|
case Archive::TarFileType::GlobalExtendedHeader: {
|
|
- TRY(tar_stream.for_each_extended_header([&](StringView key, StringView value) {
|
|
|
|
|
|
+ TRY(tar_stream->for_each_extended_header([&](StringView key, StringView value) {
|
|
if (value.length() == 0)
|
|
if (value.length() == 0)
|
|
global_overrides.remove(key);
|
|
global_overrides.remove(key);
|
|
else
|
|
else
|
|
@@ -114,7 +127,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
case Archive::TarFileType::ExtendedHeader: {
|
|
case Archive::TarFileType::ExtendedHeader: {
|
|
- TRY(tar_stream.for_each_extended_header([&](StringView key, StringView value) {
|
|
|
|
|
|
+ TRY(tar_stream->for_each_extended_header([&](StringView key, StringView value) {
|
|
local_overrides.set(key, value);
|
|
local_overrides.set(key, value);
|
|
}));
|
|
}));
|
|
break;
|
|
break;
|
|
@@ -124,11 +137,11 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|
VERIFY_NOT_REACHED();
|
|
VERIFY_NOT_REACHED();
|
|
}
|
|
}
|
|
|
|
|
|
- TRY(tar_stream.advance());
|
|
|
|
|
|
+ TRY(tar_stream->advance());
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
|
|
- Archive::TarFileStream file_stream = tar_stream.file_contents();
|
|
|
|
|
|
+ Archive::TarFileStream file_stream = tar_stream->file_contents();
|
|
|
|
|
|
// Handle other header types that don't just have an effect on extraction.
|
|
// Handle other header types that don't just have an effect on extraction.
|
|
switch (header.type_flag()) {
|
|
switch (header.type_flag()) {
|
|
@@ -143,7 +156,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|
}
|
|
}
|
|
|
|
|
|
local_overrides.set("path", long_name.to_string());
|
|
local_overrides.set("path", long_name.to_string());
|
|
- TRY(tar_stream.advance());
|
|
|
|
|
|
+ TRY(tar_stream->advance());
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
default:
|
|
default:
|
|
@@ -204,9 +217,8 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|
// Non-global headers should be cleared after every file.
|
|
// Non-global headers should be cleared after every file.
|
|
local_overrides.clear();
|
|
local_overrides.clear();
|
|
|
|
|
|
- TRY(tar_stream.advance());
|
|
|
|
|
|
+ TRY(tar_stream->advance());
|
|
}
|
|
}
|
|
- file_stream.close();
|
|
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|