Line data Source code
1 : /**
2 : * @file
3 : *
4 : * @brief
5 : *
6 : * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
7 : */
8 :
9 : #include <get.hpp>
10 :
11 : #include <cmdline.hpp>
12 : #include <kdb.hpp>
13 :
14 : #include <kdbmacros.h>
15 : #include <kdbproposal.h> // for some options
16 :
17 : #include <iostream>
18 :
19 : #include <kdbmacros.h>
20 :
21 : using namespace std;
22 : using namespace kdb;
23 :
24 374 : GetCommand::GetCommand ()
25 : {
26 374 : }
27 :
28 : namespace
29 : {
30 :
31 2 : void printOptions (option_t options)
32 : {
33 : // :'<,'>s/\(.*\)/^Iif(options \& \1) std::cout << "\1 ";
34 2 : if (options & KDB_O_DEL) std::cout << "KDB_O_DEL ";
35 2 : if (options & KDB_O_POP) std::cout << "KDB_O_POP ";
36 2 : if (options & KDB_O_NODIR) std::cout << "KDB_O_NODIR ";
37 2 : if (options & KDB_O_DIRONLY) std::cout << "KDB_O_DIRONLY ";
38 2 : if (options & KDB_O_NOREMOVE) std::cout << "KDB_O_NOREMOVE ";
39 2 : if (options & KDB_O_REMOVEONLY) std::cout << "KDB_O_REMOVEONLY ";
40 2 : if (options & KDB_O_INACTIVE) std::cout << "KDB_O_INACTIVE ";
41 2 : if (options & KDB_O_SYNC) std::cout << "KDB_O_SYNC ";
42 2 : if (options & KDB_O_SORT) std::cout << "KDB_O_SORT ";
43 2 : if (options & KDB_O_NORECURSIVE) std::cout << "KDB_O_NORECURSIVE ";
44 2 : if (options & KDB_O_NOCASE) std::cout << "KDB_O_NOCASE ";
45 2 : if (options & KDB_O_WITHOWNER) std::cout << "KDB_O_WITHOWNER ";
46 2 : if (options & KDB_O_NOALL) std::cout << "KDB_O_NOALL ";
47 :
48 2 : if (options & ckdb::KDB_O_SPEC) std::cout << "KDB_O_SPEC ";
49 2 : if (options & ckdb::KDB_O_CREATE) std::cout << "KDB_O_CREATE ";
50 2 : if (options & ckdb::KDB_O_NOCASCADING) std::cout << "KDB_O_NOCASCADING ";
51 2 : if (options & ckdb::KDB_O_NOSPEC) std::cout << "KDB_O_NOSPEC ";
52 2 : if (options & ckdb::KDB_O_NODEFAULT) std::cout << "KDB_O_NODEFAULT ";
53 2 : if (options & ckdb::KDB_O_CALLBACK) std::cout << "KDB_O_CALLBACK";
54 2 : }
55 :
56 :
57 379 : ckdb::Key * warnOnMeta (ELEKTRA_UNUSED ckdb::KeySet * ks, ELEKTRA_UNUSED ckdb::Key * key, ckdb::Key * found, option_t options)
58 : {
59 379 : if (found && !strncmp (keyName (found), "spec/", 5) && options == ckdb::KDB_O_CALLBACK)
60 : {
61 7 : const ckdb::Key * meta = keyGetMeta (found, "context");
62 7 : if (meta)
63 : {
64 : std::cout << "WARNING " << keyName (found)
65 0 : << " is context dependent, shown result might be wrong, -v shows you the trace to the key" << std::endl;
66 : }
67 : }
68 379 : return found;
69 : }
70 :
71 12 : std::string getCascadingName (std::string name)
72 : {
73 12 : if (name[0] == '/') return name;
74 15 : if (name.find ('/') == std::string::npos) return "/";
75 9 : return name.substr (name.find ('/'));
76 : }
77 : } // namespace
78 :
79 8 : ckdb::Key * printTrace (ELEKTRA_UNUSED ckdb::KeySet * ks, ckdb::Key * key, ckdb::Key * found, option_t options)
80 : {
81 8 : warnOnMeta (ks, key, found, options);
82 :
83 16 : Key k (key);
84 16 : Key f (found);
85 :
86 40 : std::string lastKeyName = k.getMeta<std::string> ("callback/print_trace/last_key_name");
87 32 : int depth = k.getMeta<int> ("callback/print_trace/depth");
88 :
89 20 : for (int i = 0; i < depth; ++i)
90 12 : std::cout << " ";
91 :
92 32 : std::cout << "searching " << (k.getName ()[0] == '/' ? "default of spec" : "") << k.getName ()
93 59 : << ", found: " << (found ? f.getName () : "<nothing>");
94 :
95 8 : if (options)
96 : {
97 2 : std::cout << ", options: ";
98 2 : printOptions (options);
99 : }
100 8 : std::cout << std::endl;
101 :
102 32 : if (k.getName ().substr (0, 5) == "spec/" && (options & ckdb::KDB_O_CALLBACK))
103 : {
104 2 : depth += 4;
105 8 : k.setMeta<int> ("callback/print_trace/depth", depth);
106 : }
107 : else
108 : {
109 42 : if (getCascadingName (lastKeyName) != getCascadingName (k.getName ()))
110 : {
111 3 : if (depth != 0)
112 : {
113 0 : depth -= 2;
114 : }
115 12 : k.setMeta<int> ("callback/print_trace/depth", depth);
116 : }
117 : }
118 40 : k.setMeta<string> ("callback/print_trace/last_key_name", k.getName ());
119 :
120 8 : f.release ();
121 8 : k.release ();
122 16 : return found;
123 : }
124 :
125 :
126 296 : int GetCommand::execute (Cmdline const & cl)
127 : {
128 592 : if (cl.arguments.size () != 1) throw invalid_argument ("Need one argument");
129 :
130 592 : KeySet conf;
131 :
132 592 : kdb::Key root = cl.createKey (0);
133 592 : kdb::KDB kdb (root);
134 :
135 592 : std::string n;
136 296 : if (cl.all)
137 : {
138 0 : n = root.getName ();
139 0 : root.setName ("/");
140 : }
141 :
142 296 : kdb.get (conf, root);
143 :
144 294 : if (cl.all)
145 : {
146 0 : root.setName (n);
147 : }
148 :
149 : // do a lookup without tracer to warm up default cache
150 588 : conf.lookup (root);
151 :
152 294 : root.setCallback (warnOnMeta);
153 294 : if (cl.verbose)
154 : {
155 25 : cout << "got " << conf.size () << " keys" << std::endl;
156 5 : root.setCallback (printTrace);
157 : }
158 588 : Key k = conf.lookup (root);
159 :
160 294 : int ret = 0;
161 :
162 294 : if (k)
163 : {
164 286 : if (cl.verbose)
165 : {
166 15 : if (k.getName ()[0] == '/')
167 : {
168 1 : cout << "The key was not found in any other namespace, taking the default from the metadata" << std::endl;
169 : }
170 25 : cout << "The resulting keyname is " << k.getName () << std::endl;
171 15 : cout << "The resulting value size is " << k.getStringSize () << std::endl;
172 : }
173 :
174 286 : if (k.isBinary ())
175 : {
176 11 : if (cl.verbose)
177 : {
178 2 : if (k.getBinarySize () == 0)
179 : {
180 2 : cout << "The key is null." << std::endl;
181 : }
182 : else
183 : {
184 0 : cout << "The key is binary." << std::endl;
185 : }
186 : }
187 11 : cout << std::hex;
188 : const uint8_t * data = static_cast<const uint8_t *> (k.getValue ());
189 130 : for (auto position = 0; position < k.getBinarySize (); position++)
190 : {
191 108 : cout << "\\x" << unsigned(data[position]);
192 : }
193 : cout << std::dec;
194 : }
195 : else
196 : {
197 825 : cout << k.getString ();
198 : }
199 : }
200 : else
201 : {
202 32 : cerr << "Did not find key '" << root.getName () << "'";
203 8 : ret = 11;
204 : }
205 :
206 294 : if (!cl.noNewline)
207 : {
208 : cout << endl;
209 : }
210 :
211 294 : printWarnings (cerr, root, cl.verbose, cl.debug);
212 294 : printError (cerr, root, cl.verbose, cl.debug);
213 :
214 588 : return ret;
215 : }
216 :
217 374 : GetCommand::~GetCommand ()
218 : {
219 7538 : }
|