From e724e21f9e0b6b67c5f436c3919a0fe2e1a5c4b1 Mon Sep 17 00:00:00 2001 From: Michael Krayer Date: Tue, 16 Feb 2021 17:35:07 +0100 Subject: [PATCH] initial commit --- README.md | 10 ++++ build | 2 + src/partialdump.cc | 119 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 131 insertions(+) create mode 100644 README.md create mode 100755 build create mode 100644 src/partialdump.cc diff --git a/README.md b/README.md new file mode 100644 index 0000000..44f6266 --- /dev/null +++ b/README.md @@ -0,0 +1,10 @@ +patialdump +--- +Extracts a given number of bytes from a file at a given offset. + +Usage: +```bash +partialdump [-j nbytes] [-N nbytes] file + -j nbytes number of bytes to skip from the beginning of file (default: 0) + -N nbytes number of bytes to read (default: -1, until EOF) +``` diff --git a/build b/build new file mode 100755 index 0000000..a48da31 --- /dev/null +++ b/build @@ -0,0 +1,2 @@ +#!/bin/bash +g++ -o partialdump src/partialdump.cc diff --git a/src/partialdump.cc b/src/partialdump.cc new file mode 100644 index 0000000..7f9917c --- /dev/null +++ b/src/partialdump.cc @@ -0,0 +1,119 @@ +#include +#include +#include +#include +using namespace std; + +const long IO_BUFFSIZE=(long)1024*1024; // read 1 KiB at a time + +/* + * Command line parsing routines + * https://stackoverflow.com/questions/865668/parsing-command-line-arguments-in-c + */ +char* getCmdOption(char** begin, char** end, const std::string& option){ + char ** itr = std::find(begin, end, option); + if(itr!=end && ++itr!=end) + { + return *itr; + } + return 0; +} + +bool cmdOptionExists(char** begin, char** end, const std::string& option){ + return std::find(begin,end,option)!=end; +} + +void print_usage(char* argv[]){ + cerr << "Usage: " << argv[0] << " [-j nbytes] [-N nbytes] file" << endl; + cerr << "Extracts a given number of bytes from a file at a given offset." << endl; + cerr << " -j nbytes number of bytes to skip from the beginning of file (default: 0)" << endl; + cerr << " -N nbytes number of bytes to read (default: -1, until EOF)" << endl; + return; +} + +/* + * Main program + */ + +int main(int argc,char *argv[]){ + int iblock; + char* buffer = new char[IO_BUFFSIZE]; + long filesize, iosize; + + if(argc==1){ + print_usage(argv); + return 0; + } + + // We expect the following command line arguments + // -h print help + // -j nbytes skip the first nbytes + // -N nbytes read nbytes + // 1 positional argument: filename + int argc_opt = argc-1; + if(cmdOptionExists(argv,argv+argc,"-h")){ + print_usage(argv); + return 0; + } + char* arg_jump = getCmdOption(argv,argv+argc_opt,"-j"); + char* arg_size = getCmdOption(argv,argv+argc_opt,"-N"); + long ijump=0, isize=-1; + if(arg_jump){ + try{ + ijump = stol(arg_jump); + } + catch(const invalid_argument& ia){ + cerr << "Invalid argument to " << ia.what() << ": " << arg_jump << endl; + return 2; + } + } + if(arg_size){ + try{ + isize = stol(arg_size); + } + catch(const invalid_argument& ia){ + cerr << "Invalid argument to " << ia.what() << ": " << arg_size << endl; + return 2; + } + } + string filename=argv[argc-1]; + + ifstream file(filename,ios::in|ios::binary); + if(!file){ + cerr << "Cannot open file: " << filename << endl; + return 3; + } + + // If we are supposed to read until the end of file, determine + // the file size. + if(isize==-1){ + file.seekg(0,ios::end); + filesize = (long)file.tellg(); + isize = filesize-ijump; + } + + // Seek to beginning of partition to read + file.seekg(ijump,ios::beg); + + // Read block by block + iblock=0; + bool trunc = false; + while(!trunc){ + trunc = (isize-iblock*IO_BUFFSIZE)