{"id":20088228,"url":"https://github.com/alexistm/untar","last_synced_at":"2025-05-06T02:32:44.340Z","repository":{"id":44688595,"uuid":"66314463","full_name":"AlexisTM/untar","owner":"AlexisTM","description":"Untar aims to simplify the extractaction of tar files with NO dependency and with ease, in C++.","archived":false,"fork":false,"pushed_at":"2024-02-22T13:54:38.000Z","size":292,"stargazers_count":16,"open_issues_count":0,"forks_count":5,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-09T07:36:28.927Z","etag":null,"topics":["compression","cpp","in-memory","tar"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AlexisTM.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2016-08-22T23:03:26.000Z","updated_at":"2025-01-02T08:03:14.000Z","dependencies_parsed_at":"2024-02-22T14:51:32.621Z","dependency_job_id":"d9a9ca2c-bcb7-433d-921f-23fdee18a8e7","html_url":"https://github.com/AlexisTM/untar","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlexisTM%2Funtar","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlexisTM%2Funtar/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlexisTM%2Funtar/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AlexisTM%2Funtar/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AlexisTM","download_url":"https://codeload.github.com/AlexisTM/untar/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252609796,"owners_count":21775882,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["compression","cpp","in-memory","tar"],"created_at":"2024-11-13T16:12:53.716Z","updated_at":"2025-05-06T02:32:43.882Z","avatar_url":"https://github.com/AlexisTM.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"untar - In memory c++ TAR extraction implementation\n=========\n\nNOTE: This project was developed before being versed in C++ and was unmaintained since (as I completely forgot about it and what I meant to use it for). You could use it as an example though, but I advise you to verify the code.\n\nAnother *simplified* c++ tar inflate implementation with *no dependency*. This implementation keeps the file open while the tarFile object is instantiated and gives you a map of tarEntry object which can each inflate themselves on demand. It is *your job* to create the files. This library only gives your the streams.\n\n**Untar** has been developed to compress SFML assets into one main file.\n\nInstallation\n---------\n\n* Download one release\n* Add untar/includes in the includes of your project or in your include dirs.\n* Add `#include \"untar/untar.h\"` in your headers\n* You are ready to go !\n\nQuick test\n----------\n\nYou can test it quickly if you have g++ installed and a bash interpreter.\n\n```bash\ngit clone https://github.com/AlexisTM/untar\ncd untar\n./build.sh\n./build/demo ./build/example.tar\n```\n\nPros/cons\n---------\n\n### Pros\n* No dependency\n* Extraction in memory (... only ...)\n* Map of tarEntry\n* map.find is O(log(N)), which is incredibly faster when you have many files than a list which is O(N)\n* Keep the file open, ready to read\n* Only read headers to be faster\n* Checksum verification\n\n### Cons\n* No extraction on disk\n* No compression (not needed in my project, if you need it, feel free to contribute !)\n* You probably need to overload the final functon (in tarEntry) to fits your needs\n* Not final version, but useful\n\nUsage\n---------\n\n```cpp\n#include \"untar/untar.h\"\n\nusing namespace untar;\n\nint main(int argc, char **argv) {\n    untar::tarFile* file;\n    ++argv; /* Skip program name */\n    if (*argv == NULL) {\n    \treturn 1;\n    }\n\n    file = new untar::tarFile(*argv, untar::File);\n\n    // We now have all the files ready to be extracted.\n    // If we want to find a file called Mommy.txt, use the map.find method\n    // First define the key you are looking for. This is the filename in the tar\n    // For example : myFolder/Mommy.txt\n    string key = \"myFolder/Mommy.txt\";\n\n    // Find the file itself\n    auto it = file-\u003eentries.find(key);\n\n    // If the file we found is NOT the end of the map (which means we did not find it), then extract the data !\n    if (it != file-\u003eentries.end())\n    {\n        untar::tarEntry * data = it-\u003esecond;\n\n        // Get the ifstream, startbyte and filesize in one call\n        size_t start;\n        int filesize;\n        std::ifstream * _tarfile = data-\u003ewantToExtract(\u0026filesize, \u0026start);\n\n        // NOTE : file-\u003e_tarfile.is_open() is the same as the one in the entries.\n        // tarFile::_tarfile will be private in future release, it is for debugging reason\n\n        // CARE THE OVERFLOW, ALWAYS\n        char dataoutput[500];\n\n        // always be sure the file is open before trying to read. Else we got shitty random data.\n        if(_tarfile-\u003eis_open()){\n\n           // Go to the beginning of the file and read the whole file\n           _tarfile-\u003eseekg(data-\u003egetStartingByte(), ios_base::beg);\n\n           // Read the data\n           _tarfile-\u003eread(dataoutput, filesize);\n\n           // Show the result\n           std::cout \u003c\u003c string(dataoutput, filesize);\n        }\n    }\n\n    delete file;\n    system(\"pause\");\n\n    return (0);\n}\n```\n\nDocumentation\n---------\n\nWaiting for a better documentation.\n\n```cpp\nnamespace untar {\n\t// Type of file in the TAR documentation\n\tenum tarEntryType {\n\t\tFileCompatibilityType = '\\0',\n\t\tFileType = '0',\n\t\tHardlinkType = '1',\n\t\tSymlinkType,\n\t\tCharacterDeviceType,\n\t\tBlockDeviceType,\n\t\tDirType,\n\t\tFifoType,\n\t\tReservedType,\n\t\tOtherType\n\t};\n\n\t// Limit entries to Files or Dir to limit the map size\n\tenum tarMode {\n\t\tFile = 1,\n\t\tHardlink = 2,\n\t\tSymlink = 4,\n\t\tCharacterDevice = 8,\n\t\tBlockDevice = 16,\n\t\tDir = 32,\n\t\tFifo = 64,\n\t\tReserved = 128,\n\t\tAll = 255\n\t};\n\n\t// The tarEntry class represents an ENTRY inside a TAR file. It can be a File, Dir, Symlink, ... Important parts to be able to use it :\n\t// tarEntry::tarEntry(string filename, int filesize, size_t startOfFile, tarEntryType type, string parentTarFilename, ifstream * _tarfile);\n\t// ifstream * tarEntry::wantToExtract(int * filesize, size_t * startInMemory);\n\t// string getFilename();\n\t// size_t getStartingByte();\n\tclass tarEntry {\n\t\tfriend class tarFile;\n\tpublic :\n\t\t// To be able to create null tarEntry\n\t\ttarEntry();\n\t\t// Default constructor, prefer this one\n\t\ttarEntry(string filename, int filesize, size_t startOfFile, tarEntryType type, string parentTarFilename, ifstream * _tarfile);\n\t\t// Constructor to avoid error for people who failed the instantiation. Could disapear when I will have properly documented the library.\n\t\ttarEntry(tarEntry const \u0026 cpy);\n\t\t// Destructor\n\t\t~tarEntry();\n\t\t// Get the tar filename where this file comes from\n\t\tstring getParentFilename();\n\t\t// Get the file size\n\t\tint getFileSize();\n\t\t// Get the filename (containing the path)\n\t\tstring getFilename();\n\t\t// Get the starting byte in the stream\n\t\tsize_t getStartingByte();\n\t\t// Get the tar type. Is it a DirType, FileType, SymlinkType ?\n\t\ttarEntryType getType();\n\t\t// Get all usefull data we need to extract our data in one call\n\t\tifstream * tarEntry::wantToExtract(int * filesize, size_t * startInMemory);\n\n\tprivate:\n\t\t// The stream, this is the same as the one of the tarFile object. Opened by default.\n\t\tstd::ifstream * _tarfile;\n\t\t// If the file is extacted, set to true.\n\t\t// For future usage, in my project in SFML\n\t\tbool _extracted;\n\t\t// Starting byte in the tar file (stream)\n\t\tsize_t _startOfFile;\n\t\t// Filesize\n\t\tint _filesize;\n\t\t// Filename (containing the path)\n\t\tstring _filename;\n\t\t// Type of the entry\n\t\ttarEntryType _type;\n\t\t// What is my dad TAR ?\n\t\tstring  _parentTarFilename;\n\t};\n\n\t// tarFile represents a TAR FILE opened. Important parts to be able to use it :\n\t// tarFile::tarFile(char * filename, int filter = All);\n\t// static map\u003cstring, tarEntry *\u003e tarFile::entries\n\tclass tarFile {\n\t\tfriend class tarEntry;\n\tpublic:\n\t\t// If you don't give a filename, don't forget to initiate via tarFile::open(...)\n\t\ttarFile();\n\t\t// Default initiation\n\t\ttarFile(char * filename, int filter = All);\n\t\t// The destructor\n\t\t~tarFile();\n\n\t\t// Open a file in case you didn't instanciated the class with a filename\n\t\tvoid open(char * filename, int filter = All);\n\t\t// Get the filename of the opened file\n\t\tstring getFilename();\n\t\t// Map of tarEntries, containing all the files\n\t\t// TODO\n\t\t// Put entries as private and wrap the find function in the class\n\t\tstatic map\u003cstring, tarEntry *\u003e entries;\n\t\t// This is the tar filestream\n\t\tstatic std::ifstream _tarfile;\n\n\tprivate:\n\t\t// Read the file and store entries\n\t\tvoid getAllEntries(int filter = All);\n\t\t// Add a new tarEntry into the map (entries)\n\t\tvoid tarFile::addEntryToMap(string filename, int filesize, tarEntryType type);\n\t\t// Check if the header is Null. The tar file ends on two Null headers\n\t\tbool isNullHeader(const char *p);\n\t\t// Verify the checksum, actually, it stops the reading on error\n\t\tstatic int verifyChecksum(const char *p);\n\t\t// Used to read the header\n\t\tstatic int parseoct(const char *p, size_t n);\n\t\t// Did we get entries ? If yes, don't get them again\n\t\tbool _get_all_entries;\n\t\t// Remember where comes the data form\n\t\tchar * _filename;\n\t};\n\n}\n```\n\nInspiration\n---------\n\n* [ctar from libarchive](https://github.com/libarchive/libarchive/blob/master/contrib/untar.c)\n* [tarlib](http://www.codeproject.com/Articles/470999/tarlib-Windows-TAR-Library)\n\nTodo\n---------\n\n* Error handling\n* Add functions to extract to system files directly\n* Compression\n\nContributing\n---------\n\n* Fork the project\n* Make a branch\n* Edit the branch\n* Make a pull request from that branch\n\nCredits\n---------\n\nAlexis Paques (@AlexisTM)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexistm%2Funtar","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falexistm%2Funtar","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexistm%2Funtar/lists"}