1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
|
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <libkdumpfile/kdumpfile.h>
static int list_attr_recursive(kdump_ctx_t *, kdump_attr_ref_t *, int);
static int show_attr(kdump_ctx_t *, kdump_attr_ref_t *, int, const char *);
static int
list_attr_recursive(kdump_ctx_t *ctx, kdump_attr_ref_t *dir, int indent)
{
kdump_attr_iter_t it;
kdump_status status;
int ret;
status = kdump_attr_ref_iter_start(ctx, dir, &it);
if (status != KDUMP_OK) {
fprintf(stderr, "kdump_attr_ref_iter_start failed: %s\n",
kdump_get_err(ctx));
return -1;
}
ret = 0;
while (it.key) {
ret = show_attr(ctx, &it.pos, indent, it.key);
if (ret)
break;
status = kdump_attr_iter_next(ctx, &it);
if (status != KDUMP_OK) {
fprintf(stderr, "kdump_attr_iter_next failed: %s\n",
kdump_get_err(ctx));
ret = -1;
break;
}
}
kdump_attr_iter_end(ctx, &it);
return ret;
}
static int
print_bitmap(kdump_ctx_t *ctx, kdump_bmp_t *bmp)
{
kdump_addr_t idx;
const char *delim = "";
kdump_status status;
idx = 0;
fputs("[ ", stdout);
while ( (status = kdump_bmp_find_set(bmp, &idx)) == KDUMP_OK) {
kdump_addr_t start = idx;
status = kdump_bmp_find_clear(bmp, &idx);
if (status != KDUMP_OK) {
fprintf(stderr, "kdump_bmp_find_clear failed: %s\n",
kdump_bmp_get_err(bmp));
return -1;
}
printf("%s%llx-%llx",
delim,
(unsigned long long) start,
(unsigned long long) idx - 1);
delim = ", ";
}
fputs("]\n", stdout);
return 0;
}
static int
print_blob(kdump_ctx_t *ctx, kdump_blob_t *blob)
{
unsigned char *data;
size_t size;
data = kdump_blob_pin(blob);
size = kdump_blob_size(blob);
fputs("[ ", stdout);
while (size--)
printf("%02X", *data++);
fputs(" ]\n", stdout);
kdump_blob_unpin(blob);
return 0;
}
static int
show_attr(kdump_ctx_t *ctx, kdump_attr_ref_t *ref, int indent, const char *key)
{
kdump_attr_t attr;
kdump_status status;
if (key && *key) {
printf("%*s%s: ", indent * 2, "", key);
++indent;
}
status = kdump_attr_ref_get(ctx, ref, &attr);
if (status != KDUMP_OK) {
fprintf(stderr, "kdump_attr_ref_get failed: %s\n",
kdump_get_err(ctx));
return -1;
}
switch (attr.type) {
case KDUMP_STRING:
printf("%s\n", attr.val.string);
break;
case KDUMP_NUMBER:
printf("%llu\n", (unsigned long long) attr.val.number);
break;
case KDUMP_ADDRESS:
printf("%llx\n", (unsigned long long) attr.val.address);
break;
case KDUMP_BITMAP:
print_bitmap(ctx, attr.val.bitmap);
break;
case KDUMP_BLOB:
print_blob(ctx, attr.val.blob);
break;
case KDUMP_DIRECTORY:
if (key && *key)
putchar('\n');
list_attr_recursive(ctx, ref, indent);
break;
default:
printf("<unknown>\n");
}
return 0;
}
int
main(int argc, char **argv)
{
if (argc < 2 || argc > 3) {
fprintf(stderr, "Usage: %s <dumpfile> [<attr>]\n", argv[0]);
return 1;
}
int fd = open(argv[1], O_RDONLY);
if (fd < 0) {
perror(argv[1]);
return 2;
}
kdump_status res;
kdump_ctx_t *ctx = kdump_new();
if (!ctx) {
perror("Cannot allocate kdump context");
return -1;
}
res = kdump_set_filename(ctx, argv[1]);
if (res != KDUMP_OK)
fprintf(stderr, "Warning: Cannot set file name: %s\n",
kdump_get_err(ctx));
res = kdump_open_fd(ctx, fd);
if (res != KDUMP_OK) {
fprintf(stderr, "File initialization failed: %s\n",
kdump_get_err(ctx));
kdump_free(ctx);
return 2;
}
kdump_attr_ref_t root;
res = kdump_attr_ref(ctx, argv[2], &root);
if (res != KDUMP_OK) {
fprintf(stderr, "kdump_attr_ref failed: %s\n",
kdump_get_err(ctx));
kdump_free(ctx);
return 2;
}
if (show_attr(ctx, &root, 0, argv[2])) {
kdump_free(ctx);
return 2;
}
kdump_attr_unref(ctx, &root);
kdump_free(ctx);
close(fd);
return 0;
}
|