Project

General

Profile

Statistics
| Branch: | Tag: | Revision:

gdp / apps / gdp-log-view.c @ master

History | View | Annotate | Download (11.9 KB)

1
/* vim: set ai sw=4 sts=4 ts=4 : */
2

    
3
/***********************************************************************
4
**  ----- BEGIN LICENSE BLOCK -----
5
**        Applications for the Global Data Plane
6
**        From the Ubiquitous Swarm Lab, 490 Cory Hall, U.C. Berkeley.
7
**
8
**        Copyright (c) 2015-2019, Regents of the University of California.
9
**        All rights reserved.
10
**
11
**        Permission is hereby granted, without written agreement and without
12
**        license or royalty fees, to use, copy, modify, and distribute this
13
**        software and its documentation for any purpose, provided that the above
14
**        copyright notice and the following two paragraphs appear in all copies
15
**        of this software.
16
**
17
**        IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
18
**        SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST
19
**        PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
20
**        EVEN IF REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
21
**
22
**        REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
23
**        LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24
**        FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION,
25
**        IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO
26
**        OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
27
**        OR MODIFICATIONS.
28
**  ----- END LICENSE BLOCK -----
29
***********************************************************************/
30

    
31
#include <ep/ep.h>
32
#include <ep/ep_dbg.h>
33
#include <ep/ep_hash.h>
34
#include <ep/ep_hexdump.h>
35
#include <ep/ep_net.h>
36
#include <ep/ep_prflags.h>
37
#include <ep/ep_string.h>
38
#include <ep/ep_time.h>
39
#include <ep/ep_xlate.h>
40
#include <gdp/gdp.h>
41

    
42
#include <dirent.h>
43
#include <errno.h>
44
#include <getopt.h>
45
#include <inttypes.h>
46
#include <stddef.h>
47
#include <stdint.h>
48
#include <stdio.h>
49
#include <string.h>
50
#include <sysexits.h>
51
#include <time.h>
52
#include <sys/stat.h>
53

    
54
// leverage existing code (this is a hack!)
55
#define GDP_LOG_VIEW        1
56
#define Dbg                                DbgLogdSqlite
57
#include "../gdplogd/logd_sqlite.c"
58
#undef Dbg
59
#include "../gdp/gdp_hongd.h"
60

    
61

    
62
/*
63
**  GDP-LOG-VIEW --- display raw on-disk storage
64
**
65
**                Not for user consumption.
66
**                This does peek into private header files.
67
*/
68

    
69
static EP_DBG        Dbg = EP_DBG_INIT("gdp-log-view", "Dump GDP logs for debugging");
70

    
71

    
72
#define LIST_NO_METADATA                0x00000001        // only list logs with no metadata
73

    
74

    
75
void
76
pr_pubkey(uint32_t md_id, uint32_t md_len, uint8_t *mdata, int plev)
77
{
78
        {
79
                int keylen = mdata[2] << 8 | mdata[3];
80
                printf("\tmd_alg %s (%d), keytype %s (%d), keylen %d\n",
81
                                ep_crypto_md_alg_name(mdata[0]), mdata[0],
82
                                ep_crypto_keytype_name(mdata[1]), mdata[1],
83
                                keylen);
84
        }
85
        if (plev > 1)
86
        {
87
                EP_CRYPTO_KEY *key;
88

    
89
                key = ep_crypto_key_read_mem(mdata + 4,
90
                                                md_len - 4,
91
                                                EP_CRYPTO_KEYFORM_DER,
92
                                                EP_CRYPTO_F_PUBLIC);
93
                ep_crypto_key_print(key, stdout, EP_CRYPTO_F_PUBLIC);
94
                ep_crypto_key_free(key);
95
        }
96
        if (plev >= 4)
97
                ep_hexdump(mdata + 4, md_len - 4, stdout, EP_HEXDUMP_HEX, 0);
98
}
99

    
100

    
101
EP_STAT
102
pr_verbose_metadata(gdp_gob_t *gob, int plev)
103
{
104
        gdp_md_t *md = gob->gob_md;
105

    
106
        printf("\n    --------------- Metadata ---------------\n");
107
        if (md == NULL)
108
        {
109
                fprintf(stderr, "%s: no metadata\n", gob->pname);
110
                return EP_STAT_ERROR;                //XXX something more specific?
111
        }
112

    
113
        int mdx = 0;
114
        for (;; ++mdx)
115
        {
116
                gdp_md_id_t md_id;
117
                size_t md_len;
118
                const uint8_t *md_data;
119
                EP_STAT estat;
120

    
121
                estat = gdp_md_get(md, mdx, &md_id, &md_len, (const void **) &md_data);
122
                EP_STAT_CHECK(estat, break);
123

    
124
                uint8_t mdata[md_len + 1];                        // +1 for null-terminator
125
                memcpy(mdata, md_data, md_len);
126
                mdata[md_len] = '\0';
127

    
128
                if (plev > 1)
129
                {
130
                        int printtype = 0;
131
                        fprintf(stdout,
132
                                        "\nMetadata entry %d: name 0x%08" PRIx32
133
                                        ", len %zd",
134
                                        mdx, md_id, md_len);
135
                        switch (md_id)
136
                        {
137
                                case GDP_MD_XID:
138
                                        printf(" (external id)\n");
139
                                        printtype = 1;
140
                                        break;
141

    
142
                                case GDP_MD_NONCE:
143
                                        printf(" (nonce)\n    ");
144
                                        ep_hexdump(mdata, md_len, stdout, EP_HEXDUMP_TERSE, 0);
145
                                        printtype = 0;
146
                                        break;
147

    
148
                                case GDP_MD_CTIME:
149
                                        printf(" (creation time)\n");
150
                                        printtype = 1;
151
                                        break;
152

    
153
                                case GDP_MD_EXPIRE:
154
                                        printf(" (expiration time)\n");
155
                                        printtype = 1;
156
                                        break;
157

    
158
                                case GDP_MD_CREATOR:
159
                                        printf(" (creator)\n");
160
                                        printtype = 1;
161
                                        break;
162

    
163
                                case GDP_MD_PUBKEY:
164
                                        printf(" (public key, deprecated)\n");
165
                                        pr_pubkey(md_id, md_len, mdata, plev);
166
                                        break;
167

    
168
                                case GDP_MD_OWNERPUBKEY:
169
                                        printf(" (owner public key)\n");
170
                                        pr_pubkey(md_id, md_len, mdata, plev);
171
                                        break;
172

    
173
                                case GDP_MD_WRITERPUBKEY:
174
                                        printf(" (writer public key)\n");
175
                                        pr_pubkey(md_id, md_len, mdata, plev);
176
                                        break;
177

    
178
                                case GDP_MD_SYNTAX:
179
                                        printf(" (syntax)\n");
180
                                        printtype = 1;
181
                                        break;
182

    
183
                                case GDP_MD_LOCATION:
184
                                        printf(" (location)\n");
185
                                        printtype = 1;
186
                                        break;
187

    
188
                                default:
189
                                        printf("\n");
190
                                        printtype = 1;
191
                                        break;
192
                        }
193
                        if (printtype == 1)
194
                        {
195
                                printf("\t%s", EpChar->lquote);
196
                                ep_xlate_out(mdata, md_len,
197
                                                stdout, "", EP_XLATE_PLUS | EP_XLATE_NPRINT);
198
                                fprintf(stdout, "%s\n", EpChar->rquote);
199
                        }
200
                        else if (printtype == 2)
201
                        {
202
                                ep_hexdump(mdata, md_len, stdout, EP_HEXDUMP_HEX, 0);
203
                        }
204
                        else if (printtype == 3)
205
                        {
206
                                ep_hexdump(mdata, md_len, stdout, EP_HEXDUMP_ASCII, 0);
207
                        }
208
                }
209
                else if (md_id == GDP_MD_XID)
210
                {
211
                        fprintf(stdout, "\tExternal name: %s\n", mdata);
212
                }
213
                else if (md_id == GDP_MD_CREATOR)
214
                {
215
                        fprintf(stdout, "\tCreator:       %s\n", mdata);
216
                }
217
                else if (md_id == GDP_MD_CTIME)
218
                {
219
                        fprintf(stdout, "\tCreation Time: %s\n", mdata);
220
                }
221

    
222
                if (plev >= 4)
223
                {
224
                        ep_hexdump(mdata, md_len, stdout, EP_HEXDUMP_ASCII, 0);
225
                }
226
        }
227
        return EP_STAT_OK;
228
}
229

    
230

    
231
static EP_STAT
232
show_rec(EP_STAT estat, gdp_datum_t *datum, gdp_result_ctx_t *ctx)
233
{
234
        uintptr_t ptrint = (uintptr_t) ctx;
235
        uint32_t pflags = (uint32_t) ptrint;
236
        if (EP_STAT_IS_SAME(estat, GDP_STAT_ACK_CONTENT))
237
                gdp_datum_print(datum, stdout, pflags);
238
        else
239
                ep_app_message(estat, "show_rec: unknown estat");
240
        return EP_STAT_OK;
241
}
242

    
243

    
244
EP_STAT
245
show_log(gdp_name_t log_name, int plev)
246
{
247
        gdp_pname_t log_pname;
248
        gdp_gob_t *gob = NULL;
249
        EP_STAT estat;
250

    
251
        (void) gdp_printable_name(log_name, log_pname);
252
        if (plev <= 0)
253
        {
254
                printf("%s\n", log_pname);
255
                return EP_STAT_OK;
256
        }
257

    
258
        // create a GOB data structure for this log
259
        estat = _gdp_gob_new(log_name, &gob);
260
        EP_STAT_CHECK(estat, return estat);
261
        gob->x = (struct gdp_gob_xtra *) ep_mem_zalloc(sizeof *gob->x);
262
        _gdp_gob_lock(gob);
263

    
264
        // open the on-disk database
265
        estat = sqlite_open(gob);
266
        EP_STAT_CHECK(estat, goto fail0);
267

    
268
        // figure out what we want to actually print
269
        if (plev == 1)
270
        {
271
                // show log name, number of records, external name if known
272
                size_t md_len;
273
                const void *md_data;
274

    
275
                estat = gdp_md_find(gob->gob_md, GDP_MD_XID, &md_len, &md_data);
276
                if (!EP_STAT_ISOK(estat))
277
                {
278
                        md_data = (void *) "-";
279
                        md_len = 1;
280
                }
281
                printf("%s %" PRIgdp_recno " %.*s\n",
282
                                log_pname, gob->nrecs, (int) md_len, (const char *) md_data);
283
                goto done;
284
        }
285
        if (plev == 2)
286
        {
287
                // show log name, nrecs, brief metadata overview
288
                printf("%s %" PRIgdp_recno "\n", log_pname, gob->nrecs);
289
                gdp_md_t *md = gob->gob_md;
290
                if (md == NULL)
291
                        goto done;
292
                int mdx = 0;
293
                for (;; mdx++)
294
                {
295
                        gdp_md_id_t md_id;
296
                        size_t md_len;
297
                        const uint8_t *md_data;
298

    
299
                        estat = gdp_md_get(md, mdx, &md_id, &md_len, (const void **) &md_data);
300
                        EP_STAT_CHECK(estat, break);
301

    
302
                        int ptype = 0;
303
                        const char *ptag = NULL;
304
                        switch (md_id)
305
                        {
306
                                case GDP_MD_XID:
307
                                        ptag = "external id";
308
                                        ptype = 1;
309
                                        break;
310
                                case GDP_MD_NONCE:
311
                                        ptag = "nonce";
312
                                        ptype = 2;
313
                                        break;
314
                                case GDP_MD_CTIME:
315
                                        ptag = "creation time";
316
                                        ptype = 1;
317
                                        break;
318
                                case GDP_MD_EXPIRE:
319
                                        ptag = "expiration time";
320
                                        ptype = 1;
321
                                        break;
322
                                case GDP_MD_CREATOR:
323
                                        ptag = "creator";
324
                                        ptype = 1;
325
                                        break;
326
                                case GDP_MD_PUBKEY:
327
                                        ptag = "public key, deprecated";
328
                                        break;
329
                                case GDP_MD_OWNERPUBKEY:
330
                                        ptag = "owner public key";
331
                                        break;
332
                                case GDP_MD_WRITERPUBKEY:
333
                                        ptag = "writer public key";
334
                                        break;
335
                                default:
336
                                        printf("       0x%08x len %zd ", md_id, md_len);
337
                                        break;
338
                        }
339
                        printf("  %22s ", ptag == NULL ? "" : ptag);
340
                        switch (ptype)
341
                        {
342
                        case 1:
343
                                // print as string
344
                                printf("%s", EpChar->lquote);
345
                                ep_xlate_out(md_data, md_len, stdout, "",
346
                                                EP_XLATE_PLUS | EP_XLATE_NPRINT);
347
                                printf("%s\n", EpChar->rquote);
348
                                break;
349

    
350
                        case 2:
351
                                // print as hex
352
                                ep_hexdump(md_data, md_len, stdout, EP_HEXDUMP_TERSE, 0);
353
                                break;
354

    
355
                        default:
356
                                printf("(omitted)\n");
357
                                break;
358
                        }
359
                }
360
                goto done;
361
        }
362

    
363
        if (plev >= 3)
364
                printf("\n\n----------------------------------------------------------\n");
365
        printf("%s: %" PRIgdp_recno " recs\n", log_pname, gob->nrecs);
366
        uint32_t pflags = GDP_DATUM_PRMETAONLY;
367
        if (plev >= 3)
368
        {
369
                pflags |= GDP_DATUM_PRSIG;
370
                pr_verbose_metadata(gob, plev);
371
        }
372
        if (plev >= 5)
373
                pflags &= ~GDP_DATUM_PRMETAONLY;
374

    
375
        // now dump the contents
376
        if (plev >= 4)
377
        {
378
                printf("\n    --------------- Data ---------------\n");
379
                uintptr_t intptrpflags = pflags;
380
                estat = sqlite_read_by_recno(gob, 1, UINT32_MAX, show_rec,
381
                                                                (void *) intptrpflags);
382
        }
383

    
384
        if (false)
385
        {
386
                char ebuf[60];
387
fail0:
388
                fprintf(stderr, "%s: %s\n",
389
                                log_pname, ep_stat_tostr(estat, ebuf, sizeof ebuf));
390
        }
391
done:
392
        if (gob != NULL)
393
                _gdp_gob_free(&gob);
394
        return estat;
395
}
396

    
397

    
398
int
399
list_logs(const char *gcl_dir_name, int plev)
400
{
401
        DIR *dir;
402
        int subdir;
403
        gdp_name_t gcl_iname;
404

    
405
        ep_dbg_cprintf(Dbg, 11, "list_logs(%s)\n", gcl_dir_name);
406
        dir = opendir(gcl_dir_name);
407
        if (dir == NULL)
408
        {
409
                fprintf(stderr, "Could not open %s, errno = %d\n",
410
                                gcl_dir_name, errno);
411
                return EX_NOINPUT;
412
        }
413
        closedir(dir);
414

    
415
        for (subdir = 0; subdir < 0x100; subdir++)
416
        {
417
                char dbuf[400];
418

    
419
                snprintf(dbuf, sizeof dbuf, "%s/_%02x", gcl_dir_name, subdir);
420
                dir = opendir(dbuf);
421
                if (dir == NULL)
422
                        continue;
423

    
424
                for (;;)
425
                {
426
                        struct dirent *dent;
427

    
428
                        // read the next directory entry
429
                        dent = readdir(dir);
430
                        if (dent == NULL)
431
                                break;
432

    
433
                        // we're only interested in .data files
434
                        char *p = strrchr(dent->d_name, '.');
435
                        if (p == NULL || strcmp(p, GLOG_SUFFIX) != 0)
436
                                continue;
437

    
438
                        // save the full pathname in case we need it
439
                        snprintf(dbuf, sizeof dbuf, "%s/_%02x/%s",
440
                                        gcl_dir_name, subdir, dent->d_name);
441

    
442
                        // strip off the ".db"
443
                        *p = '\0';
444

    
445
                        // print the name and maybe other info
446
                        gdp_parse_name(dent->d_name, gcl_iname);
447
                        show_log(gcl_iname, plev);
448
                }
449
                closedir(dir);
450
        }
451

    
452
        return EX_OK;
453
}
454

    
455

    
456
void
457
usage(const char *msg)
458
{
459
        fprintf(stderr,
460
                        "Usage error: %s\n"
461
                        "Usage: log-view [-d dir] [-D dbgspec ] [-l] [-r] [-v] [log_name ...]\n"
462
                        "\t-d dir -- set log database root directory\n"
463
                        "\t-D spec -- set debug flags\n"
464
                        "\t-l -- list all local logs\n"
465
                        "\t-n -- only list logs with no metadata\n"
466
                        "\t-v -- print verbose information (-vv for more detail)\n",
467
                                msg);
468

    
469
        exit(EX_USAGE);
470
}
471

    
472
int
473
main(int argc, char *argv[])
474
{
475
        int opt;
476
        int verbosity = 0;
477
        bool ls_logs = false;
478
        char *log_xname = NULL;
479
        const char *log_dir_name = NULL;
480
        EP_STAT estat;
481

    
482
//        ep_lib_init(0);
483

    
484
        while ((opt = getopt(argc, argv, "d:D:lnv")) > 0)
485
        {
486
                switch (opt)
487
                {
488
                case 'd':
489
                        log_dir_name = optarg;
490
                        break;
491

    
492
                case 'D':
493
                        ep_dbg_set(optarg);
494
                        break;
495

    
496
                case 'l':
497
                        ls_logs = true;
498
                        break;
499

    
500
                case 'v':
501
                        verbosity++;
502
                        break;
503

    
504
                default:
505
                        usage("unknown flag");
506
                }
507
        }
508
        argc -= optind;
509
        argv += optind;
510

    
511
        // initialization
512
        estat = gdp_init_phase_0(NULL, 0);
513
        EP_STAT_CHECK(estat, goto fail0);
514
        ep_adm_readparams("gdplogd");
515
        _gdp_name_init(NULL);
516

    
517
        // initialize logd_sqlite
518
        estat = sqlite_init(log_dir_name);
519
        EP_STAT_CHECK(estat, goto fail0);
520

    
521
        if (ls_logs)
522
        {
523
                if (argc > 0)
524
                        usage("cannot use a log name with -l");
525
                return list_logs(LogDir, verbosity);
526
        }
527

    
528
        if (argc <= 0)
529
                usage("log name required");
530
        for (; argc > 0; argc--, argv++)
531
        {
532
                gdp_name_t log_name;
533
                log_xname = argv[0];
534

    
535
                estat = gdp_parse_name(log_xname, log_name);
536
                if (!EP_STAT_ISOK(estat))
537
                {
538
                        ep_app_message(estat, "unparsable log name");
539
                        continue;
540
                }
541
                estat = show_log(log_name, verbosity);
542
        }
543
fail0:
544
        if (EP_STAT_ISFAIL(estat))
545
                exit(EX_UNAVAILABLE);
546
        exit(EX_OK);
547
}