From 0114829d5bbe18a2e847e87b34d3926b1fbc2f93 Mon Sep 17 00:00:00 2001 From: Marcel Nowicki Date: Thu, 10 Feb 2022 23:08:59 +0100 Subject: [PATCH] this added output to text file and proper parsing of command line arguments. this also cleaned up some more stuff. --- main.cpp | 141 +++++++++++++++++++++++++++++++++------------------- tarconst.h | 5 +- tarfunc.cpp | 20 ++++++++ tarfunc.h | 10 +++- 4 files changed, 122 insertions(+), 54 deletions(-) diff --git a/main.cpp b/main.cpp index ffbcd23..0eebabb 100644 --- a/main.cpp +++ b/main.cpp @@ -3,7 +3,6 @@ */ #include -#include #include #include #include @@ -12,71 +11,109 @@ #include "tarfunc.h" int main(int argc, char** argv) { + // Trivial check for arguments. + if (argc < 2) { + tar::printhelp(); + return 9; + } // GENERAL VARIABLES - //count the types of all items - std::map typecount{ - {tarconstant::typeFile, 0}, {tarconstant::typeDir, 0}, {tarconstant::typeSym, 0}, - {tarconstant::typeHard, 0}, {tarconstant::typeOther, 0} - }; - uint64_t sizeof_allfiles{}; // total size of all files in the archive - - // Trivial check for arguments. Errorprone and has to be changed. - if (argc < 2) { - std::cout << tarconstant::helptext << '\n'; - return 9; + // Load command line parameters into vector, read them and set variables + std::vector cmdparam{}; + for (int i = 1; i < argc; i++){ + cmdparam.emplace_back(argv[i]); } - // Getting name from argument lists on startup. Trivial and errorprone. Placeholder for now. - std::string archiveFilename(argv[1]); + bool toFile = false; + bool toJSON = false; - for (int i = 0; i < argc; i++){ - std::cout << argv[i] << '\n'; + std::vector archiveFilename {}; + for (auto i : cmdparam) { + if (i[0] != '-' && i.size() > 1) { + archiveFilename.push_back(i); + } + if (i[0] == '-') { + for (auto j : i) { + switch (j) { + case 'j': + toJSON = true; + break; + case 'f': + toFile = true; + break; + case 'h': + tar::printhelp(); + return 9; + case '-': + break; + default: + std::cout << "Invalid optional argument '" << j << "'!" << '\n' << '\n'; + tar::printhelp(); + return 9; + } + } + } } - //Open tar File. - std::ifstream file(archiveFilename, std::ios::binary); - if(!file) { - std::cout << "Error opening file!" << '\n' << '\n'; - std::cout << tarconstant::helptext << '\n'; - return 9; - } + for (auto &archiveName : archiveFilename) { + //count the types of all items + std::map typecount{ + {tarconstant::typeFile, 0}, {tarconstant::typeDir, 0}, {tarconstant::typeSym, 0}, + {tarconstant::typeHard, 0}, {tarconstant::typeOther, 0} + }; - if (!tar::validTar(file)) { - std::cout << archiveFilename << " is not a valid tar file for tarstats-pp" << '\n'; - return 9; - } + uint64_t sizeof_allfiles{}; // total size of all files in the archive - while (file) { - //Read header of next item in tar archive - char *headbuffer = new char[tarconstant::blocksize]; - file.read(headbuffer, tarconstant::blocksize); - - // tar file ends with 2 512byte blocks of 0. As no block should ever be 0 unless at the end, we check only once. - if (tar::eof(headbuffer)) { - break; + //Open tar File. + std::ifstream file(archiveName, std::ios::binary); + if (!file) { + std::cout << "Error opening file " << archiveName << "!" << '\n' << '\n'; + tar::printhelp(); + return 9; } - // Read type of item - std::string itemtype = tar::getitemtype(headbuffer[tarconstant::itemtypeByte]); - typecount[itemtype] += 1; - - // read itemsize and add to total - sizeof_allfiles += tar::getitemsize(headbuffer); - - // ignore file content. we want to get to the next header. item types != FILE have no content blocks (0 byte) - if (tar::getitemsize(headbuffer)!=0) { - file.ignore((tar::getitemsize(headbuffer) / tarconstant::blocksize) - * tarconstant::blocksize + tarconstant::blocksize); + if (!tar::validTar(file)) { + std::cout << "!!!!!!!" << '\n'; + std::cout << archiveName << " is not a valid tar file for tarstats-pp" << '\n'; + std::cout << "!!!!!!!" << '\n' << '\n'; } + else { + while (file) { + //Read header of next item in tar archive + char *headbuffer = new char[tarconstant::blocksize]; + file.read(headbuffer, tarconstant::blocksize); - // empty the headerbuffer - delete[] headbuffer; + // tar file ends with 2 512byte blocks of 0. As no block should ever be 0 unless at the end, we check only once. + if (tar::eof(headbuffer)) { + break; + } + + // Read type of item + std::string itemtype = tar::getitemtype(headbuffer[tarconstant::itemtypeByte]); + typecount[itemtype] += 1; + + // read itemsize and add to total + sizeof_allfiles += tar::getitemsize(headbuffer); + + // ignore file content. we want to get to the next header. item types != FILE have no content blocks (0 byte) + if (tar::getitemsize(headbuffer) != 0) { + file.ignore((tar::getitemsize(headbuffer) / tarconstant::blocksize) + * tarconstant::blocksize + tarconstant::blocksize); + } + + // empty the headerbuffer + delete[] headbuffer; + } + file.close(); + + std::cout << toJSON << '\n'; + tar::consolestats(typecount, std::filesystem::file_size(archiveName), sizeof_allfiles); + if (toFile) { + tar::txtfilestats(typecount, std::filesystem::file_size(archiveName), sizeof_allfiles, + archiveName); + } + } } - file.close(); - - tar::consolestats(typecount, std::filesystem::file_size(archiveFilename), sizeof_allfiles); - return 0; } diff --git a/tarconst.h b/tarconst.h index d2e208b..ed400e6 100644 --- a/tarconst.h +++ b/tarconst.h @@ -34,7 +34,10 @@ namespace tarconstant { "optional arguments\n" "-h this helptext\n" "-j stats in JSON format printed to stdout\n" - "-f print stats to file .txt or .json if -j invoked"}; + "-f print stats to file .txt or .json if -j invoked\n\n" + "Find more information as well as full source at github.com/blindi0815/Tarstats-pp." + "This software is as is under a GPL 3.0 license.\n\n" + "Written by Marcel Nowicki - github.com/blindi0815"}; } #endif //TARSTATS___TARCONST_H diff --git a/tarfunc.cpp b/tarfunc.cpp index 138d200..bded118 100644 --- a/tarfunc.cpp +++ b/tarfunc.cpp @@ -61,10 +61,30 @@ std::string tar::getitemtype(char &n) { } } +// writes stats to console in default style void tar::consolestats (std::map &typecount, uintmax_t tarfilesize, uintmax_t sizeofall) { std::cout << "Archive size: " << tarfilesize << " Bytes"<< '\n'; std::cout << "Size of all items: " << sizeofall << " Bytes" << '\n' << '\n'; for (auto &i : typecount) { std::cout << i.first <<": " << i.second << '\n'; } +} + +// writes default console output to txt file +void tar::txtfilestats (std::map &typecount, uintmax_t tarfilesize, uintmax_t sizeofall, + std::string archiveName) { + std::string txtname = archiveName + ".txt"; + std::ofstream txtfile(txtname); + txtfile << "Archive size: " << tarfilesize << " Bytes"<< std::endl; + txtfile << "Size of all items: " << sizeofall << " Bytes" << std::endl << std::endl; + for (auto &i : typecount) { + txtfile << i.first <<": " << i.second << std::endl; + } + txtfile.close(); + std::cout << "Stats written to " << txtname << '\n' << '\n'; +} + +// print out helpertext +void tar::printhelp(){ + std::cout << tarconstant::helptext << '\n' << '\n'; } \ No newline at end of file diff --git a/tarfunc.h b/tarfunc.h index bc3b668..5754f28 100644 --- a/tarfunc.h +++ b/tarfunc.h @@ -6,6 +6,7 @@ #include #include #include +#include "tarconst.h" #ifndef TARSTATS___TARFUNC_H @@ -22,8 +23,15 @@ namespace tar { // gets type of an item std::string getitemtype(char &n); -// + +// to write stats to console in default style void consolestats (std::map &typecount, uintmax_t tarfilesize, uintmax_t sizeofall); + +// to write default console output to txt file + void txtfilestats (std::map &typecount, uintmax_t tarfilesize, uintmax_t sizeofall, + std::string archiveName); +// print out helpertext + void printhelp(); }