/* * @project The CERN Tape Archive (CTA) * @copyright Copyright © 2021-2022 CERN * @license This program is free software, distributed under the terms of the GNU General Public * Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". You can * redistribute it and/or modify it under the terms of the GPL Version 3, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE. See the GNU General Public License for more details. * * In applying this licence, CERN does not waive the privileges and immunities * granted to it by virtue of its status as an Intergovernmental Organization or * submit itself to any jurisdiction. */ #include "tapeserver/tapelabel/TapeLabelCmdLineArgs.hpp" #include "common/exception/CommandLineNotParsed.hpp" #include "common/utils/utils.hpp" #include "common/Constants.hpp" #include #include #include namespace cta::tapeserver::tapelabel { //------------------------------------------------------------------------------ // constructor //------------------------------------------------------------------------------ TapeLabelCmdLineArgs::TapeLabelCmdLineArgs(const int argc, char *const *const argv): help(false), m_debug(false), m_force(false) { static struct option longopts[] = { {"vid", required_argument, nullptr, 'v'}, {"oldlabel", required_argument, nullptr, 'o'}, {"debug", no_argument, nullptr, 'd'}, {"drive", required_argument, nullptr, 'u'}, {"loadtimeout", required_argument, nullptr, 't'}, {"force", no_argument, nullptr, 'f'}, {"help", no_argument, nullptr, 'h'}, {nullptr, 0, nullptr, 0} }; // Prevent getopt() from printing an error message if it does not recognize // an option character opterr = 0; int opt = 0; while((opt = getopt_long(argc, argv, ":v:o:t:u:hdf", longopts, nullptr)) != -1) { switch(opt) { case 'v': if (strnlen(optarg, CA_MAXVIDLEN+1) > CA_MAXVIDLEN) { exception::CommandLineNotParsed ex; ex.getMessage() << "The -" << static_cast(opt) << " option too big"; throw ex; } m_vid = std::string(optarg); if (!utils::isUpper(m_vid)) { exception::CommandLineNotParsed ex; ex.getMessage() << "The -" << static_cast(opt) << " option must only contain uppercase alphanumeric characters"; throw ex; } break; case 'o': if (strnlen(optarg, CA_MAXVIDLEN+1) > CA_MAXVIDLEN) { exception::CommandLineNotParsed ex; ex.getMessage() << "The -" << static_cast(opt) << " option too big"; throw ex; } m_oldLabel = std::string(optarg); if (!utils::isUpper(m_vid)) { exception::CommandLineNotParsed ex; ex.getMessage() << "The -" << static_cast(opt) << " option must only contain uppercase alphanumeric characters"; throw ex; } break; case 't': try { m_tapeLoadTimeout = std::stoul(optarg, nullptr, 0); } catch (std::invalid_argument &) { exception::CommandLineNotParsed ex; ex.getMessage() << "Invalid value for the tape load timeout: " << optarg; throw ex; } catch (std::out_of_range &) { exception::CommandLineNotParsed ex; ex.getMessage() << "Too large value for the tape load timeout: " << optarg; throw ex; } if (!m_tapeLoadTimeout) { exception::CommandLineNotParsed ex; ex.getMessage() << "The tape load timeout cannot be 0"; throw ex; } break; case 'u': m_unitName = std::string(optarg); break; case 'h': help = true; break; case 'd': m_debug = true; break; case 'f': m_force = true; break; case ':': // Missing parameter { exception::CommandLineNotParsed ex; ex.getMessage() << "The -" << static_cast(optopt) << " option requires a parameter"; throw ex; } case '?': // Unknown option { exception::CommandLineNotParsed ex; if(0 == optopt) { ex.getMessage() << "Unknown command-line option"; } else { ex.getMessage() << "Unknown command-line option: -" << static_cast(optopt); } throw ex; } default: { exception::CommandLineNotParsed ex; ex.getMessage() << "getopt_long returned the following unknown value: 0x" << std::hex << static_cast(opt); throw ex; } } // switch(opt) } // while getopt_long() if (m_vid.empty() && !help) { exception::CommandLineNotParsed ex; ex.getMessage() << "--vid/-v VID must be specified"; throw ex; } // There is no need to continue parsing when the help option is set if(help) { return; } } //------------------------------------------------------------------------------ // printUsage //------------------------------------------------------------------------------ void TapeLabelCmdLineArgs::printUsage(std::ostream &os) { os << "Usage:" << std::endl << " cta-tape-label [options] --vid/-v VID" << std::endl << "Where:" << std::endl << " -v, --vid The VID of the tape to be labeled" << std::endl << "Options:" <