1 /*===========================================================================
2 *
3 * PUBLIC DOMAIN NOTICE
4 * National Center for Biotechnology Information
5 *
6 * This software/database is a "United States Government Work" under the
7 * terms of the United States Copyright Act. It was written as part of
8 * the author's official duties as a United States Government employee and
9 * thus cannot be copyrighted. This software/database is freely available
10 * to the public for use. The National Library of Medicine and the U.S.
11 * Government have not placed any restriction on its use or reproduction.
12 *
13 * Although all reasonable efforts have been taken to ensure the accuracy
14 * and reliability of the software and data, the NLM and the U.S.
15 * Government do not and cannot warrant the performance or results that
16 * may be obtained by using this software or data. The NLM and the U.S.
17 * Government disclaim all warranties, express or implied, including
18 * warranties of performance, merchantability or fitness for any particular
19 * purpose.
20 *
21 * Please cite the author in any work or product based on this material.
22 *
23 * ===========================================================================
24 *
25 */
26
27 #include <kfg/extern.h>
28
29 #include <kfg/config.h>
30 #include <kfg/repository.h> /* KRepositoryMgr */
31 #include <kfg/kfg-priv.h>
32
33 #include <klib/namelist.h> /* KNamelistRelease */
34 #include <klib/out.h> /* OUTMSG */
35 #include <klib/klib-priv.h>
36 #include <klib/rc.h>
37
38 #include <kfs/directory.h>
39 #include <kfs/dyload.h> /* KDyld */
40 #include <kfs/file.h> /* KFileRead */
41 #include <kfs/nullfile.h> /* KFileMakeNullUpdate */
42 #include <kfs/md5.h> /* KMD5SumFmt */
43
44 #include <sysalloc.h>
45
46 #include <stdarg.h> /* va_start */
47 #include <stdio.h> /* sprintf */
48 #include <stdlib.h> /* malloc */
49 #include <string.h> /* memset */
50 #include <limits.h> /* PATH_MAX */
51 #include <assert.h>
52
53 #ifndef PATH_MAX
54 #define PATH_MAX 4096
55 #endif
56
57 #define RELEASE(type, obj) do { rc_t rc2 = type##Release(obj); \
58 if (rc2 && !rc) { rc = rc2; } obj = NULL; } while (false)
59
60 /*
61 * An unrecoverable error happened.
62 * We can help to solve it
63 * by reporting information about known application execution environment.
64 */
65
66 #define report ( * f -> report )
67 #define reportData ( * f -> reportData )
68 #define reportData1 ( * f -> reportData1 )
69 #define reportOpen ( * f -> reportOpen )
70 #define reportOpen1 ( * f -> reportOpen1 )
71 #define reportClose ( * f -> reportClose )
72 #define reportClose1 ( * f -> reportClose1 )
73 #define reportError ( * f -> reportError )
74 #define reportErrorStr ( * f -> reportErrorStr )
75 #define reportErrorStrImpl ( * f -> reportErrorStrImpl )
76 #define reportErrorStrInt ( * f -> reportErrorStrInt )
77 #define reportError3Str ( * f -> reportError3Str )
78
ReportKfgFiles(const ReportFuncs * f,int indent,const KConfig * cfg)79 static rc_t ReportKfgFiles(const ReportFuncs *f,
80 int indent, const KConfig* cfg)
81 {
82 rc_t rc = 0;
83
84 uint32_t count = 0;
85 KNamelist* names = NULL;
86
87 rc = KConfigListIncluded(cfg, &names);
88
89 if (rc != 0) {
90 reportOpen(indent, "Files", 0);
91 reportError(indent + 1, rc, "KConfigListIncluded");
92 }
93 else {
94 rc = KNamelistCount(names, &count);
95 if (rc != 0) {
96 reportOpen(indent, "Files", 0);
97 reportErrorStr(indent + 1,
98 rc, "KNamelistCount", "origin", "KConfigListIncluded");
99 }
100 else {
101 uint32_t i = 0;
102 reportOpen(indent, "Files", 1, "count", 'd', count);
103 for (i = 0; i < count && rc == 0; ++i) {
104 const char* name = NULL;
105 rc = KNamelistGet(names, i, &name);
106 if (rc != 0) {
107 reportErrorStrInt(indent + 1, rc, "KNamelistGet",
108 "origin", "KConfigListIncluded", "idx", i);
109 }
110 else
111 { report(indent + 1, "File", 1, "name", 's', name); }
112 }
113 }
114 }
115 reportClose(indent, "Files");
116
117 RELEASE(KNamelist, names);
118
119 return rc;
120 }
121
122 static
sKConfigNode_Read(const KConfigNode * node,char * buffer,size_t buf_sz,char ** overflow_buf,bool * cant_allocate)123 rc_t sKConfigNode_Read(const KConfigNode* node, char* buffer, size_t buf_sz,
124 char** overflow_buf, bool* cant_allocate)
125 {
126 rc_t rc = 0;
127 size_t num_read = 0;
128 size_t remaining = 0;
129 assert(overflow_buf && cant_allocate);
130 *cant_allocate = false;
131 *overflow_buf = NULL;
132 rc = KConfigNodeRead(node, 0, buffer, buf_sz, &num_read, &remaining);
133 if (rc != 0)
134 { return rc; }
135 if (num_read < buf_sz)
136 { buffer[num_read] = '\0'; }
137 else {
138 size_t new_buf_sz = num_read + remaining + 1;
139 char* overflow = malloc(new_buf_sz);
140 if (overflow == NULL) {
141 int i = 0;
142 for (i = 2; i < 5 && buf_sz - i > 0; ++i)
143 { buffer[buf_sz - i] = '.'; }
144 buffer[buf_sz - 1] = '\0';
145 *cant_allocate = true;
146 }
147 else {
148 buffer = *overflow_buf = overflow;
149 buf_sz =
150 rc = KConfigNodeRead
151 (node, 0, buffer, new_buf_sz, &num_read, &remaining);
152 if (rc != 0)
153 { return rc; }
154 assert(num_read < new_buf_sz && remaining == 0);
155 buffer[num_read] = '\0';
156 }
157 }
158 return rc;
159 }
160
161 static rc_t ReportChildNode(const ReportFuncs *f, int indent,
162 const KNamelist* names, const KConfigNode* node, const char* root, uint32_t idx);
163
164 static
ReportConfigNodeChildren(const ReportFuncs * f,int indent,const KConfigNode * node,const char * nodeName)165 rc_t ReportConfigNodeChildren(const ReportFuncs *f, int indent,
166 const KConfigNode* node, const char* nodeName)
167 {
168 KNamelist* names = NULL;
169 rc_t rc = KConfigNodeListChild(node, &names);
170 if (rc != 0) {
171 reportErrorStrImpl(indent,
172 rc, "KConfigNodeListChild", "node", nodeName, false);
173 }
174 else {
175 uint32_t count = 0;
176 rc = KNamelistCount(names, &count);
177 if (rc != 0) {
178 reportErrorStrImpl
179 (indent, rc, "KNamelistCount", "node", nodeName, false);
180 }
181 else {
182 if (count) {
183 uint32_t i = 0;
184 int j;
185 OUTMSG(("\n"));
186 for (i = 0; i < count && rc == 0; ++i) {
187 rc = ReportChildNode
188 (f, indent + 1, names, node, nodeName, i);
189 }
190 for (j = 0; j < indent; ++j)
191 { OUTMSG((" ")); }
192 }
193 }
194 }
195 RELEASE(KNamelist, names);
196 return rc;
197 }
198
ReportConfigNode(const ReportFuncs * f,int indent,const char * root,const char * name,const KConfigNode * node,const char * node_name)199 static rc_t ReportConfigNode(const ReportFuncs *f, int indent, const char* root,
200 const char* name, const KConfigNode* node, const char* node_name)
201 {
202 rc_t rc = 0;
203
204 char local[PATH_MAX + 1] = "";
205 const char* nodeName = node_name ? node_name : name;
206 char* overflow = NULL;
207 bool cantallocate = false;
208
209 reportOpen1(indent, nodeName);
210 rc = sKConfigNode_Read(node, local, sizeof local, &overflow, &cantallocate);
211 if (rc == 0) {
212 char* buf = overflow ? overflow : local;
213 rc = reportData1(buf);
214 free(overflow);
215 overflow = NULL;
216 if (rc == 0)
217 { rc = ReportConfigNodeChildren(f, indent, node, nodeName); }
218 }
219 else {
220 reportError3Str
221 (indent + 1, rc, "KConfigNodeRead", "node", root, "/", name, false);
222 }
223 reportClose1(nodeName);
224
225 return rc;
226 }
227
ReportConfigNode_File(const ReportFuncs * f,int indent,const char * root,const char * name,const KConfigNode * node,const char * node_name)228 static rc_t ReportConfigNode_File(const ReportFuncs *f, int indent,
229 const char* root,
230 const char* name, const KConfigNode* node, const char* node_name)
231 {
232 rc_t rc = 0;
233 char local[PATH_MAX + 1] = "";
234 const char* nodeName = node_name ? node_name : name;
235 char* overflow = NULL;
236 bool cantallocate = false;
237 rc = sKConfigNode_Read(node, local, sizeof local, &overflow, &cantallocate);
238 if (rc) {
239 reportError3Str
240 (indent, rc, "KConfigNodeRead", "node", root, "/", name, false);
241 }
242 else {
243 const char* buf = overflow ? overflow : local;
244 KPathType file_type = kptNotFound;
245 const char* type = NULL;
246 if (!cantallocate) {
247 KDirectory* dir = NULL;
248 rc = KDirectoryNativeDir(&dir);
249 if (rc == 0) {
250 file_type = KDirectoryPathType(dir, "%s", buf);
251 file_type &= ~kptAlias;
252 type = file_type == kptFile ? "exists" :
253 file_type == kptNotFound ? "not found" : "unexpected";
254 }
255 RELEASE(KDirectory, dir);
256 }
257 else
258 { type = "noo long"; }
259 if (rc == 0)
260 { reportData(indent, nodeName, buf, 1, "file", 's', type); }
261 }
262 free(overflow);
263 overflow = NULL;
264 return rc;
265 }
266
ReportChildNode(const ReportFuncs * f,int indent,const KNamelist * names,const KConfigNode * node,const char * root,uint32_t idx)267 static rc_t ReportChildNode(const ReportFuncs *f, int indent,
268 const KNamelist* names,
269 const KConfigNode* node, const char* root, uint32_t idx)
270 {
271 rc_t rc = 0;
272
273 const char* name = NULL;
274 rc = KNamelistGet(names, idx, &name);
275 if (rc != 0) {
276 reportErrorStrInt
277 (indent + 1, rc, "KNamelistGet", "node", root, "idx", idx);
278 }
279 else {
280 const KConfigNode* child = NULL;
281
282 rc = KConfigNodeOpenNodeRead(node, &child, "%s", name);
283 if (rc != 0) {
284 reportOpen(indent, name, 0);
285 reportError3Str(indent + 1, rc, "KConfigNodeOpenNodeRead",
286 "node", root, "/", name, true);
287 reportClose(indent, name);
288 }
289 else {
290 rc = ReportConfigNode(f, indent, root, name, child, NULL);
291 }
292
293 RELEASE(KConfigNode, child);
294 }
295
296 return rc;
297 }
298
299 static
ReportRefseq(const ReportFuncs * f,int indent,const KConfig * cfg)300 rc_t ReportRefseq(const ReportFuncs *f, int indent, const KConfig* cfg)
301 {
302 rc_t rc = 0;
303
304 const char root[] = "refseq";
305
306 const KConfigNode* node = NULL;
307 rc = KConfigOpenNodeRead(cfg, &node, "%s", root);
308 if (rc != 0) {
309 if (GetRCState(rc) == rcNotFound) {
310 report(indent, root, 1, "state", 's', "not found");
311 rc = 0;
312 }
313 else
314 { reportErrorStr(indent, rc, "KConfigOpenNodeRead", "node", root); }
315 }
316 else {
317 KNamelist* names = NULL;
318 rc = KConfigNodeListChild(node, &names);
319 if (rc != 0)
320 { reportErrorStr(indent, rc, "KConfigNodeListChild", "node", root); }
321 else {
322 uint32_t count = 0;
323 rc = KNamelistCount(names, &count);
324 if (rc != 0)
325 { reportErrorStr(indent, rc, "KNamelistCount", "node", root); }
326 else {
327 uint32_t i = 0;
328 reportOpen(indent, root, 0);
329 for (i = 0; i < count && rc == 0; ++i)
330 { rc = ReportChildNode(f, indent + 1, names, node, root, i); }
331 reportClose(indent, root);
332 }
333 }
334 RELEASE(KNamelist, names);
335 }
336
337 RELEASE(KConfigNode, node);
338
339 return rc;
340 }
341
342 static
ReportSra(const ReportFuncs * f,int indent,const KConfig * cfg)343 rc_t ReportSra(const ReportFuncs *f, int indent, const KConfig* cfg)
344 {
345 rc_t rc = 0;
346 const char root[] = "sra";
347 const KConfigNode* node = NULL;
348 assert(cfg);
349 rc = KConfigOpenNodeRead(cfg, &node, "%s", root);
350 if (rc != 0) {
351 if (GetRCState(rc) == rcNotFound) {
352 report(indent, root, 1, "state", 's', "not found");
353 rc = 0;
354 }
355 else
356 { reportErrorStr(indent, rc, "KConfigOpenNodeRead", "node", root); }
357 }
358 else {
359 KNamelist* names = NULL;
360 rc = KConfigNodeListChild(node, &names);
361 if (rc != 0)
362 { reportErrorStr(indent, rc, "KConfigNodeListChild", "node", root); }
363 else {
364 uint32_t count = 0;
365 rc = KNamelistCount(names, &count);
366 if (rc != 0)
367 { reportErrorStr(indent, rc, "KNamelistCount", "node", root); }
368 else {
369 uint32_t i = 0;
370 reportOpen(indent, root, 0);
371 for (i = 0; i < count && rc == 0; ++i)
372 { rc = ReportChildNode(f, indent + 1, names, node, root, i); }
373 reportClose(indent, root);
374 }
375 }
376 RELEASE(KNamelist, names);
377 }
378 RELEASE(KConfigNode, node);
379 return rc;
380 }
381
382 static
ReportKrypto(const ReportFuncs * f,int indent,const KConfig * cfg)383 rc_t ReportKrypto(const ReportFuncs *f, int indent, const KConfig* cfg)
384 {
385 rc_t rc = 0;
386
387 const char root[] = KFG_KRYPTO_PWFILE;
388 const char name[] = "krypto";
389
390 const KConfigNode* node = NULL;
391 rc = KConfigOpenNodeRead(cfg, &node, "%s", root);
392 if (rc != 0) {
393 if (GetRCState(rc) == rcNotFound) {
394 report(indent, name, 1, "state", 's', "pwfile: not found");
395 rc = 0;
396 }
397 else
398 { reportErrorStr(indent, rc, "KConfigOpenNodeRead", "node", root); }
399 }
400 else {
401 rc = ReportConfigNode_File(f, indent, "krypto", "pwfile", node, "krypto");
402 }
403
404 RELEASE(KConfigNode, node);
405
406 return rc;
407 }
408
ReportRemoteAccess(const ReportFuncs * f,int indent,const KRepositoryMgr * mgr)409 static rc_t ReportRemoteAccess(const ReportFuncs *f,
410 int indent, const KRepositoryMgr *mgr)
411 {
412 const char root[] = "RemoteAccess";
413
414 bool available = KRepositoryMgrHasRemoteAccess(mgr);
415 report(indent, root, 1, "available", 's', available ? "true" : "false");
416
417 return 0;
418 }
419
ReportCrntRepository(const ReportFuncs * f,int indent,const KRepositoryMgr * mgr)420 static rc_t ReportCrntRepository(const ReportFuncs *f,
421 int indent, const KRepositoryMgr *mgr)
422 {
423 rc_t rc = 0;
424
425 const KRepository *protectd = NULL;
426
427 const char root[] = "CurrentProtectedRepository";
428 bool open = false;
429
430 if (rc == 0) {
431 rc = KRepositoryMgrCurrentProtectedRepository(mgr, &protectd);
432 if (rc != 0) {
433 if (rc == SILENT_RC(
434 rcKFG, rcMgr, rcAccessing, rcNode, rcNotFound))
435 {
436 report(indent, root, 1, "found", 's', "false");
437 }
438 else {
439 reportOpen(indent, root, 0);
440 open = true;
441 reportErrorStr(indent + 1, rc,
442 "KRepositoryMgrCurrentProtectedRepository", NULL, NULL);
443 }
444 }
445 }
446 if (rc == 0) {
447 char buffer[256];
448 size_t name_size = 0;
449 reportOpen(indent, root, 1, "found", 's', "true");
450 open = true;
451 rc = KRepositoryName(protectd, buffer, sizeof buffer, &name_size);
452 if (rc != 0) {
453 reportErrorStr(indent + 1, rc, "KRepositoryName",
454 "origin", "KRepositoryMgrCurrentProtectedRepository");
455 }
456 else {
457 reportData(indent + 1, "name", buffer, 0);
458 }
459 }
460 if (open) {
461 reportClose(indent, root);
462 }
463
464 RELEASE(KRepository, protectd);
465
466 return rc;
467 }
468
ReportKfg(const ReportFuncs * f,uint32_t indent,uint32_t skipCount,va_list args)469 rc_t ReportKfg
470 ( const ReportFuncs *f, uint32_t indent, uint32_t skipCount, va_list args )
471 {
472 rc_t rc = 0;
473
474 KConfig *cfg = NULL;
475 const KRepositoryMgr *mgr = NULL;
476
477 const char tag[] = "Configuration";
478
479 reportOpen(indent, tag, 0);
480
481 rc = KConfigMake(&cfg, NULL);
482 if (rc != 0) {
483 reportError(indent + 1, rc, "KConfigMake");
484 }
485 else if ((rc = KConfigMakeRepositoryMgrRead(cfg, &mgr)) != 0) {
486 reportError(indent + 1, rc, "KConfigMakeRepositoryMgrRead");
487 }
488 else {
489 {
490 rc_t rc2 = ReportKfgFiles(f, indent + 1, cfg);
491 if (rc == 0 && rc2 != 0)
492 { rc = rc2; }
493 }
494 {
495 rc_t rc2 = ReportRefseq(f, indent + 1, cfg);
496 if (rc == 0 && rc2 != 0)
497 { rc = rc2; }
498 }
499 {
500 rc_t rc2 = ReportKrypto(f, indent + 1, cfg);
501 if (rc == 0 && rc2 != 0)
502 { rc = rc2; }
503 }
504 {
505 rc_t rc2 = ReportSra(f, indent + 1, cfg);
506 if (rc == 0 && rc2 != 0)
507 { rc = rc2; }
508 }
509 {
510 rc_t rc2 = KConfigPrintPartial(cfg, indent, skipCount, args);
511 if (rc == 0 && rc2 != 0)
512 { rc = rc2; }
513 }
514 {
515 rc_t rc2 = ReportRemoteAccess(f, indent + 1, mgr);
516 if (rc == 0 && rc2 != 0)
517 { rc = rc2; }
518 }
519 {
520 rc_t rc2 = ReportCrntRepository(f, indent + 1, mgr);
521 if (rc == 0 && rc2 != 0)
522 { rc = rc2; }
523 }
524 }
525
526 reportClose(indent, tag);
527
528 RELEASE(KRepositoryMgr, mgr);
529 RELEASE(KConfig, cfg);
530
531 return rc;
532 }
533