GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/publish/command.cc
Date: 2024-04-28 02:33:07
Exec Total Coverage
Lines: 0 69 0.0%
Branches: 0 131 0.0%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 */
4
5 #include "cvmfs_config.h"
6 #include "publish/command.h"
7
8 #include <getopt.h>
9
10 #include <cassert>
11 #include <cstdlib>
12 #include <cstring>
13
14 #include "publish/except.h"
15 #include "util/logging.h"
16 #include "util/smalloc.h"
17 #include "util/string.h"
18
19 using namespace std; // NOLINT
20
21 namespace publish {
22
23 std::string Command::GetExamples() const {
24 std::vector<std::string> examples = DoGetExamples();
25 std::string result;
26 for (unsigned i = 0; i < examples.size(); ++i) {
27 result += progname() + " " + GetName() + " " + examples[i] + "\n";
28 }
29 return result;
30 }
31
32
33 Command::Options Command::ParseOptions(int argc, char **argv) {
34 Options result;
35 progname_ = argv[0];
36 ParameterList params = GetParams();
37
38 string shortopts;
39 struct option *longopts = reinterpret_cast<option *>(
40 smalloc((params.size() + 1) * sizeof(struct option)));
41 struct option lastopt;
42 memset(&lastopt, 0, sizeof(lastopt));
43 longopts[params.size()] = lastopt;
44
45 for (unsigned i = 0; i < params.size(); ++i) {
46 shortopts.push_back(params[i].short_key);
47 if (!params[i].is_switch) shortopts.push_back(':');
48
49 longopts[i].name = strdup(params[i].key.c_str());
50 longopts[i].has_arg = params[i].is_switch ? no_argument : required_argument;
51 longopts[i].flag = NULL;
52 longopts[i].val = params[i].short_key;
53 }
54
55 int idx;
56 int c;
57 opterr = 0; // Don't print error messages in getopt
58 optind = 2; // Skip the command itself
59 while ((c = getopt_long(argc, argv, shortopts.c_str(), longopts, &idx)) != -1)
60 {
61 bool found = false;
62 for (unsigned i = 0; i < params.size(); ++i) {
63 if (c == params[i].short_key) {
64 Argument argument;
65 if (!params[i].is_switch) {
66 argument.value_str = optarg;
67 argument.value_int = String2Int64(argument.value_str);
68 }
69 result.Set(params[i], argument);
70 found = true;
71 break;
72 }
73 }
74
75 if (!found) {
76 assert(c == '?');
77 // Easier to duplicate the next few lines than to add an RAII wrapper
78 for (unsigned i = 0; i < params.size(); ++i) {
79 free(const_cast<char *>(longopts[i].name));
80 }
81 free(longopts);
82
83 throw EPublish(GetName() + ": unrecognized parameter '" +
84 argv[optind - 1] + "'", EPublish::kFailInvocation);
85 }
86 }
87
88 for (unsigned i = 0; i < params.size(); ++i) {
89 free(const_cast<char *>(longopts[i].name));
90 }
91 free(longopts);
92
93 for (unsigned i = 0; i < params.size(); ++i) {
94 if (!params[i].is_optional && !result.Has(params[i].key)) {
95 throw EPublish(
96 GetName() + ": missing mandatory parameter '" + params[i].key + "'",
97 EPublish::kFailInvocation);
98 }
99 }
100
101 for (int i = optind; i < argc; ++i) {
102 result.AppendPlain(Argument(argv[i]));
103 }
104
105 if (result.plain_args().size() < GetMinPlainArgs()) {
106 LogCvmfs(kLogCvmfs, kLogStderr, "Usage: %s %s %s",
107 progname().c_str(), GetName().c_str(), GetUsage().c_str());
108 throw EPublish(GetName() + ": missing argument", EPublish::kFailInvocation);
109 }
110
111 return result;
112 }
113
114
115 //------------------------------------------------------------------------------
116
117
118 CommandList::~CommandList() {
119 for (unsigned i = 0; i < commands_.size(); ++i)
120 delete commands_[i];
121 }
122
123 Command *CommandList::Find(const std::string &name) {
124 Command *result = NULL;
125 for (unsigned i = 0; i < commands_.size(); ++i) {
126 if (commands_[i]->GetName() == name) {
127 result = commands_[i];
128 break;
129 }
130 }
131 return result;
132 }
133
134 void CommandList::TakeCommand(Command *command) {
135 assert(Find(command->GetName()) == NULL);
136 commands_.push_back(command);
137 }
138
139 } // namespace publish
140