From 2af7cf5adf272fed61ab5899f6dfab5ab10dbe56 Mon Sep 17 00:00:00 2001 From: Marcel Nowicki Date: Thu, 10 Feb 2022 19:24:38 +0100 Subject: [PATCH] this added a check if the given file is a valid tar by checking the magic field for ustar this also cleaned up some stringliterals. --- main.cpp | 53 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/main.cpp b/main.cpp index c5b2313..5d18a5e 100644 --- a/main.cpp +++ b/main.cpp @@ -6,6 +6,24 @@ #include #include +// global itemtype definition +std::string const typeFile = "FILES"; +std::string const typeDir = "DIRECTORIES"; +std::string const typeSym = "SYMLINKS"; +std::string const typeHard = "HARDLINKS"; +std::string const typeOther = "OTHER"; + +// checks if a valid modern tar file - ustar +bool validTar (std::istream & file) { + file.seekg(257); + char* buffer = new char [6]; + file.read(buffer, 6); + std::string magicfield(&buffer[0], 5); + delete[] buffer; + file.seekg(0); + return magicfield == "ustar" ? true: false; +} + // checks if a 512byte block consist only of 0 or \0 bool eof (const char* buf) { std::string test(&buf[0]); @@ -16,13 +34,6 @@ bool eof (const char* buf) { return 0; } -// gets name of an item (for test purposes) -std::string getitemname (const char* buf) { - std::string name (&buf[0], 100); - std::erase(name, '\0'); - return name; -} - // gets size of an item in bytes. assumes octal encoding. uint64_t getitemsize(const char* buf){ std::string asciisize(&buf[124], 11); // at offset 124 because first byte marks octal or base256 coding @@ -41,15 +52,15 @@ std::string getitemtype(char &n) { // read itemtype switch (n){ case '0': case '\0': - return "FILE "; + return typeFile; case '1': - return "HARDLINK "; + return typeHard; case '2': - return "SYMLINK "; + return typeSym; case '5': - return "DIRECTORY "; + return typeDir; default: - return "OTHER "; + return typeOther; } } @@ -59,12 +70,13 @@ int main(int argc, char** argv) { // GENERAL VARIABLES //count the types of all items - std::map typecount{ - {"FILE ", 0}, {"HARDLINK ", 0}, {"SYMLINK ", 0}, - {"DIRECTORY ", 0}, {"OTHER ", 0} + std::map typecount{ + {typeFile, 0}, {typeDir, 0}, {typeSym, 0}, + {typeHard, 0}, {typeOther, 0} }; uint64_t sizeof_allfiles{}; // total size of all files in the archive + std::string helptext {"usage: tarstats-pp [-h] [-j] [-f] tarfile.\n" "A tool to calculate basics statistics on tarball. Shamelessly inspired by github.com/isotopp/tarstats!\n\n" @@ -86,11 +98,16 @@ int main(int argc, char** argv) { //Open tar File. std::ifstream file(archiveFilename, std::ios::binary); if(!file) { - std::cout << "Error opening file" << std::endl; + std::cout << "Error opening file!" << '\n' << '\n'; std::cout << helptext << '\n'; return 9; } + if (!validTar(file)) { + std::cout << archiveFilename << " is not a valid tar file for tarstats-pp" << '\n'; + return 9; + } + // Tar spec is working with continous 512 byte size blocks. Header is 512 bytes. int buffersize = 512; while (file) { @@ -123,8 +140,8 @@ int main(int argc, char** argv) { file.close(); std::cout << "Archive size: " << std::filesystem::file_size(archiveFilename) << " Bytes"<< '\n'; std::cout << "Size of all items: " << sizeof_allfiles << " Bytes" << '\n' << '\n'; - for (auto i : typecount) { - std::cout << i.first <<": " << i.second << '\n'; + for (auto &i : typecount) { + std::cout << i.first <<": " << i.second << '\n'; } return 0;