// // .7Z, .ARC, .ARK, .BZ2, .GZ, .LHA, .LZH, .LZX, .RAR, .TAR, .TGZ, .XAR, .ZIP - libArchive for Meatloaf! // // // // https://stackoverflow.com/questions/22543179/how-to-use-libarchive-properly // // https://libarchive.org/ // #ifndef MEATLOAF_ARCHIVE // #define MEATLOAF_ARCHIVE // #include // #include // #include "meat_io.h" // #include "../../../include/debug.h" // // TODO: check how we can use archive_seek_callback, archive_passphrase_callback etc. to our benefit! // /* Returns pointer and size of next block of data from archive. */ // // The read callback returns the number of bytes read, zero for end-of-file, or a negative failure code as above. // // It also returns a pointer to the block of data read. // ssize_t cb_read(struct archive *a, void *__src_stream, const void **buff); // /* // It must return the number of bytes actually skipped, or a negative failure code if skipping cannot be done. // It can skip fewer bytes than requested but must never skip more. // Only positive/forward skips will ever be requested. // If skipping is not provided or fails, libarchive will call the read() function and simply ignore any data that it does not need. // * Skips at most request bytes from archive and returns the skipped amount. // * This may skip fewer bytes than requested; it may even skip zero bytes. // * If you do skip fewer bytes than requested, libarchive will invoke your // * read callback and discard data as necessary to make up the full skip. // */ // int64_t cb_skip(struct archive *a, void *__src_stream, int64_t request); // int64_t cb_seek(struct archive *a, void *userData, int64_t offset, int whence); // int cb_close(struct archive *a, void *__src_stream); // /******************************************************** // * Streams implementations // ********************************************************/ // class ArchiveStreamData { // public: // uint8_t *srcBuffer = nullptr; // std::shared_ptr srcStream = nullptr; // a stream that is able to serve bytes of this archive // }; // class ArchiveStream : public MStream // { // bool is_open = false; // public: // static const size_t buffSize = 256; // 4096; // ArchiveStreamData streamData; // struct archive *a; // struct archive_entry *entry; // ArchiveStream(std::shared_ptr srcStr); // ~ArchiveStream(); // bool open() override; // void close() override; // bool isOpen() override; // uint32_t read(uint8_t *buf, uint32_t size) override; // uint32_t write(const uint8_t *buf, uint32_t size) override; // // For files with a browsable random access directory structure // // d64, d74, d81, dnp, etc. // bool seekPath(std::string path) override; // // For files with no directory structure // // tap, crt, tar // //std::string seekNextEntry() override; // virtual bool seek(uint32_t pos) override; // bool isRandomAccess() override { return true; }; // bool seekEntry( std::string filename ); // protected: // private: // }; // /******************************************************** // * Files implementations // ********************************************************/ // class ArchiveContainerFile : public MFile // { // struct archive *getArchive() { // ArchiveStream* as = (ArchiveStream*)dirStream.get(); // return as->a; // } // std::shared_ptr dirStream = nullptr; // a stream that is able to serve bytes of this archive // public: // ArchiveContainerFile(std::string path) : MFile(path) // { // // media_header = name; // media_archive = name; // }; // ~ArchiveContainerFile() // { // if (dirStream.get() != nullptr) // { // dirStream->close(); // } // } // std::string basepath = ""; // //MStream* getSourceStream(std::ios_base::openmode mode=std::ios_base::in) override; // has to return OPENED stream // MStream* getDecodedStream(std::shared_ptr src) override; // // archive file is always a directory // bool isDirectory(); // bool rewindDirectory() override; // MFile *getNextFileInDir() override; // bool mkDir() override { return false; }; // bool remove() override { return true; } // bool rename(std::string dest) { return true; } // time_t getLastWrite() override { return 0; } // time_t getCreationTime() override { return 0; } // private: // bool prepareDirListing(); // bool isDir = true; // bool dirIsOpen = false; // }; // /******************************************************** // * FS implementations // ********************************************************/ // class ArchiveContainerFileSystem : public MFileSystem // { // MFile *getFile(std::string path) // { // return new ArchiveContainerFile(path); // }; // public: // ArchiveContainerFileSystem() : MFileSystem("arch") {} // bool handles(std::string fileName) // { // return byExtension( // { // ".7z", // ".arc", // ".ark", // ".bz2", // ".gz", // ".lha", // ".lzh", // ".lzx", // ".rar", // ".tar", // ".tgz", // ".xar", // ".zip" // }, // fileName // ); // } // private: // }; // #endif // MEATLOAF_ARCHIVE