// vfs_cat -- print one file from a layered VFS to stdout (for byte-equality // checks against `unzip -p`, and as a tiny inspection tool). // // vfs_cat [--registration] (--zip ARCHIVE | --native DIR)... REL // vfs_cat --list (--zip ARCHIVE | --native DIR)... [PREFIX] #include #include #include #include "mars/vfs/vfs.h" using namespace mars::vfs; int main(int argc, char** argv) { Order order = Order::NativeFirst; bool list = false; std::string rel; std::vector> mounts; // (is_zip, path) for (int i = 1; i < argc; ++i) { std::string a = argv[i]; if (a == "--registration") order = Order::Registration; else if (a == "--list") list = true; else if ((a == "--zip" || a == "--native") && i + 1 < argc) mounts.emplace_back(a == "--zip", argv[++i]); else rel = a; } if (mounts.empty() || (!list && rel.empty())) { std::fprintf(stderr, "usage: vfs_cat [--registration] (--zip A | --native D)... REL\n" " vfs_cat --list (--zip A | --native D)... [PREFIX]\n"); return 2; } Vfs v(order); for (const auto& [is_zip, path] : mounts) { auto r = is_zip ? v.mount_zip(path) : v.mount_native(path); if (!r) { std::fprintf(stderr, "mount %s: %s\n", path.c_str(), r.error().message.c_str()); return 1; } } if (list) { for (const auto& e : v.list(rel)) std::printf("%10llu m%d %s\n", static_cast(e.size), e.mount, e.name.c_str()); return 0; } auto bytes = v.read(rel); if (!bytes) { std::fprintf(stderr, "%s: %s\n", rel.c_str(), bytes.error().message.c_str()); return 1; } std::fwrite(bytes->data(), 1, bytes->size(), stdout); return 0; }