From 6aeca0eedbf7bc282effd485770c087efd96f890 Mon Sep 17 00:00:00 2001 From: Alaa Eddine Elamri Date: Fri, 8 Jul 2022 11:37:52 +0200 Subject: [PATCH] bextract: replacing custom CLI parsing with CLI11 --- core/src/stored/CMakeLists.txt | 2 +- core/src/stored/bextract.cc | 245 +++++++++--------- .../source/Appendix/BareosPrograms.rst | 34 ++- 3 files changed, 148 insertions(+), 133 deletions(-) diff --git a/core/src/stored/CMakeLists.txt b/core/src/stored/CMakeLists.txt index 727f47d7d58..1c3d7303672 100644 --- a/core/src/stored/CMakeLists.txt +++ b/core/src/stored/CMakeLists.txt @@ -236,7 +236,7 @@ add_executable(bls ${BLSSRCS}) target_link_libraries(bls PRIVATE bareos bareossd bareosfind) add_executable(bextract ${BEXTRACTSRS}) -target_link_libraries(bextract PRIVATE bareossd bareosfind bareos) +target_link_libraries(bextract PRIVATE bareossd bareosfind bareos CLI11::CLI11) add_executable(bscan ${BSCANSRCS}) target_link_libraries(bscan PRIVATE bareos bareossd bareosfind bareossql) diff --git a/core/src/stored/bextract.cc b/core/src/stored/bextract.cc index 8ea48a0e804..7c79fd2b0f0 100644 --- a/core/src/stored/bextract.cc +++ b/core/src/stored/bextract.cc @@ -44,6 +44,7 @@ #include "lib/address_conf.h" #include "lib/attribs.h" #include "lib/berrno.h" +#include "lib/cli.h" #include "lib/edit.h" #include "lib/bsignal.h" #include "lib/parse_bsr.h" @@ -56,7 +57,10 @@ extern bool ParseSdConfig(const char* configfile, int exit_code); using namespace storagedaemon; -static void DoExtract(char* devname); +static void DoExtract(char* devname, + std::string VolumeName, + BootStrapRecord* bsr, + DirectorResource* director); static bool RecordCb(DeviceControlRecord* dcr, DeviceRecord* rec); static Device* dev = NULL; @@ -64,7 +68,6 @@ static DeviceControlRecord* dcr; static BareosWinFilePacket bfd; static JobControlRecord* jcr; static FindFilesPacket* ff; -static BootStrapRecord* bsr = NULL; static bool extract = false; static int non_support_data = 0; static long total = 0; @@ -73,9 +76,6 @@ static char* where; static uint32_t num_files = 0; static int prog_name_msg = 0; static int win32_data_msg = 0; -static char* VolumeName = NULL; -static char* DirectorName = NULL; -static DirectorResource* director = NULL; static AclData acl_data; static XattrData xattr_data; @@ -85,37 +85,9 @@ static char* wbuf; /* write buffer address */ static uint32_t wsize; /* write size */ static uint64_t fileAddr = 0; /* file write address */ -static void usage() -{ - kBareosVersionStrings.PrintCopyrightWithFsfAndPlanets(stderr, 2000); - fprintf(stderr, - _("Usage: bextract " - "\n" - " -b specify a bootstrap file\n" - " -c specify a Storage configuration file or " - "directory\n" - " -D specify a director name specified in the " - "Storage\n" - " configuration file for the Key Encryption " - "Key selection\n" - " -d set debug level to \n" - " -dt print timestamp in debug output\n" - " -e exclude list\n" - " -i include list\n" - " -p proceed inspite of I/O errors\n" - " -v verbose\n" - " -V specify Volume names (separated by |)\n" - " -? print this message\n\n")); - exit(1); -} int main(int argc, char* argv[]) { - int ch; - FILE* fd; - char line[1000]; - bool got_inc = false; - setlocale(LC_ALL, ""); tzset(); bindtextdomain("bareos", LOCALEDIR); @@ -131,94 +103,128 @@ int main(int argc, char* argv[]) ff = init_find_files(); binit(&bfd); - while ((ch = getopt(argc, argv, "b:c:D:d:e:i:pvV:?")) != -1) { - switch (ch) { - case 'b': /* bootstrap file */ - bsr = libbareos::parse_bsr(NULL, optarg); - // DumpBsr(bsr, true); - break; - - case 'c': /* specify config file */ - if (configfile != NULL) { free(configfile); } - configfile = strdup(optarg); - break; - - case 'D': /* specify director name */ - if (DirectorName != NULL) { free(DirectorName); } - DirectorName = strdup(optarg); - break; - - case 'd': /* debug level */ - if (*optarg == 't') { - dbg_timestamp = true; - } else { - debug_level = atoi(optarg); - if (debug_level <= 0) { debug_level = 1; } - } - break; - - case 'e': /* exclude list */ - if ((fd = fopen(optarg, "rb")) == NULL) { - BErrNo be; - Pmsg2(0, _("Could not open exclude file: %s, ERR=%s\n"), optarg, - be.bstrerror()); - exit(1); - } - while (fgets(line, sizeof(line), fd) != NULL) { - StripTrailingJunk(line); - Dmsg1(900, "add_exclude %s\n", line); - AddFnameToExcludeList(ff, line); - } - fclose(fd); - break; - - case 'i': /* include list */ - if ((fd = fopen(optarg, "rb")) == NULL) { - BErrNo be; - Pmsg2(0, _("Could not open include file: %s, ERR=%s\n"), optarg, - be.bstrerror()); - exit(1); - } - while (fgets(line, sizeof(line), fd) != NULL) { - StripTrailingJunk(line); - Dmsg1(900, "add_include %s\n", line); - AddFnameToIncludeList(ff, 0, line); - } - fclose(fd); - got_inc = true; - break; - - case 'p': - forge_on = true; - break; + CLI::App bextract_app; + InitCLIApp(bextract_app, "The Bareos Extraction tool.", 2000); + + BootStrapRecord* bsr = nullptr; + bextract_app + .add_option( + "-b,--parse-bootstrap", + [&bsr](std::vector vals) { + bsr = libbareos::parse_bsr(NULL, vals.front().data()); + return true; + }, + "Specify a bootstrap file.") + ->check(CLI::ExistingFile) + ->type_name(""); + + bextract_app + .add_option( + "-c,--config", + [](std::vector val) { + if (configfile != nullptr) { free(configfile); } + configfile = strdup(val.front().c_str()); + return true; + }, + "Use as configuration file or directory.") + ->check(CLI::ExistingPath) + ->type_name(""); + + char* DirectorName = NULL; + bextract_app + .add_option( + "-D,--director", + [&DirectorName](std::vector val) { + if (DirectorName != nullptr) { free(DirectorName); } + DirectorName = strdup(val.front().c_str()); + return true; + }, + "Specify a director name specified in the storage.\n" + "Configuration file for the Key Encryption Key selection.") + ->type_name(""); + + AddDebugOptions(bextract_app); - case 'v': - verbose++; - break; + FILE* fd; + char line[1000]; + bextract_app + .add_option( + "-e,--exclude", + [&line, &fd](std::vector val) { + if ((fd = fopen(val.front().c_str(), "rb")) == NULL) { + BErrNo be; + Pmsg2(0, _("Could not open exclude file: %s, ERR=%s\n"), optarg, + be.bstrerror()); + exit(1); + } + while (fgets(line, sizeof(line), fd) != NULL) { + StripTrailingJunk(line); + Dmsg1(900, "add_exclude %s\n", line); + AddFnameToExcludeList(ff, line); + } + fclose(fd); + return true; + }, + "Exclude list.") + ->type_name(""); - case 'V': /* Volume name */ - VolumeName = optarg; - break; + bool got_inc = false; - case '?': - default: - usage(); - - } /* end switch */ - } /* end while */ - argc -= optind; - argv += optind; - - if (argc != 2) { - Pmsg0(0, - _("Wrong number of arguments. Make sure the last two parameters are " - " \n")); - usage(); - } + bextract_app + .add_option( + "-i,--include-list", + [&line, &fd, &got_inc](std::vector val) { + if ((fd = fopen(optarg, "rb")) == NULL) { + BErrNo be; + Pmsg2(0, _("Could not open include file: %s, ERR=%s\n"), optarg, + be.bstrerror()); + exit(1); + } + while (fgets(line, sizeof(line), fd) != NULL) { + StripTrailingJunk(line); + Dmsg1(900, "add_include %s\n", line); + AddFnameToIncludeList(ff, 0, line); + } + fclose(fd); + got_inc = true; + return true; + }, + "Include list.") + ->type_name(""); + + bextract_app.add_flag("-p,--ignore-errors", forge_on, + "Proceed inspite of IO errors."); + + AddVerboseOption(bextract_app); + + std::string VolumeNames; + bextract_app + .add_option("-V,--volumes", VolumeNames, "Volume names (separated by |).") + ->type_name(""); + + std::string archive_device_name; + bextract_app + .add_option("bareos-archive-device-name", archive_device_name, + "Specify the input device name (either as name of a Bareos " + "Storage Daemon Device resource or identical to the Archive " + "Device in a Bareos Storage Daemon Device resource).") + ->required() + ->type_name(" "); + + std::string directory_to_store_files; + bextract_app + .add_option("target-directory", directory_to_store_files, + "Specify directory where to store files.") + ->required() + ->type_name(" "); + + + CLI11_PARSE(bextract_app, argc, argv); my_config = InitSdConfig(configfile, M_ERROR_TERM); ParseSdConfig(configfile, M_ERROR_TERM); + static DirectorResource* director = nullptr; if (DirectorName) { foreach_res (director, R_DIRECTOR) { if (bstrcmp(director->resource_name_, DirectorName)) { break; } @@ -240,8 +246,8 @@ int main(int argc, char* argv[]) AddFnameToIncludeList(ff, 0, "/"); /* include everything */ } - where = argv[1]; - DoExtract(argv[0]); + where = directory_to_store_files.data(); + DoExtract(archive_device_name.data(), VolumeNames, bsr, director); if (bsr) { libbareos::FreeBsr(bsr); } if (prog_name_msg) { @@ -382,7 +388,10 @@ static void ClosePreviousStream(void) SetAttributes(jcr, attr, &bfd); } -static void DoExtract(char* devname) +static void DoExtract(char* devname, + std::string VolumeName, + BootStrapRecord* bsr, + DirectorResource* director) { struct stat statp; uint32_t decompress_buf_size; @@ -390,7 +399,7 @@ static void DoExtract(char* devname) EnableBackupPrivileges(NULL, 1); dcr = new DeviceControlRecord; - jcr = SetupJcr("bextract", devname, bsr, director, dcr, VolumeName, + jcr = SetupJcr("bextract", devname, bsr, director, dcr, VolumeName.c_str(), true); /* read device */ if (!jcr) { exit(1); } dev = jcr->impl->read_dcr->dev; diff --git a/docs/manuals/source/Appendix/BareosPrograms.rst b/docs/manuals/source/Appendix/BareosPrograms.rst index 1b45ecadded..e840cd301c9 100644 --- a/docs/manuals/source/Appendix/BareosPrograms.rst +++ b/docs/manuals/source/Appendix/BareosPrograms.rst @@ -490,21 +490,27 @@ It is called: .. code-block:: shell-session - Usage: bextract - -b specify a bootstrap file - -c specify a Storage configuration file - -D specify a director name specified in the Storage - configuration file for the Key Encryption Key selection - -d set debug level to - -dt print timestamp in debug output - -e exclude list - -i include list - -p proceed inspite of I/O errors - -v verbose - -V specify Volume names (separated by |) - -? print this message + Usage: bextract [OPTIONS] bareos-archive-device-name target-directory + + Positionals: + bareos-archive-device-name REQUIRED Specify input archive names. + target-directory REQUIRED Specify directory where to store files. + + Options: + -h,--help Print this help message and exit + -b,--parse-bootstrap Specify a bootstrap file. + -c,--config Use as configuration file or directory. + -D,--director Specify a director name specified in the storage. + Configuration file for the Key Encryption Key selection. + -d,--debug-level Set debug level to . + --dt,--debug-timestamps Print timestamp in debug output. + -e,--exclude Exclude list. + -i,--include-list Include list. + -p,--ignore-errors Proceed inspite of IO errors. + -v,--verbose Verbose user messages. + -V,--volumes Volume names (separated by |). -where device-name is the Archive Device (raw device name or full filename) of the device to be read, and directory-to-store-files is a path prefix to prepend to all the files restored. +where bareos-archive-device-name is the Archive Device (raw device name or full filename) of the device to be read, and target-directory is a path prefix to prepend to all the files restored.