📄 libdm-report.c
字号:
/* * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved. * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. * * This file is part of the device-mapper userspace tools. * * This copyrighted material is made available to anyone wishing to use, * modify, copy, or redistribute it subject to the terms and conditions * of the GNU Lesser General Public License v.2.1. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include "libdevmapper.h"#include "list.h"#include "log.h"/* * Internal flags */#define RH_SORT_REQUIRED 0x00000100#define RH_HEADINGS_PRINTED 0x00000200struct dm_report { struct dm_pool *mem; uint32_t report_types; const char *field_prefix; uint32_t flags; const char *separator; uint32_t keys_count; /* Ordered list of fields needed for this report */ struct list field_props; /* Rows of report data */ struct list rows; /* Array of field definitions */ const struct dm_report_field_type *fields; const struct dm_report_object_type *types; /* To store caller private data */ void *private;};/* * Internal per-field flags */#define FLD_HIDDEN 0x00000100#define FLD_SORT_KEY 0x00000200#define FLD_ASCENDING 0x00000400#define FLD_DESCENDING 0x00000800struct field_properties { struct list list; uint32_t field_num; uint32_t sort_posn; int32_t width; const struct dm_report_object_type *type; uint32_t flags;};/* * Report data field */struct dm_report_field { struct list list; struct field_properties *props; const char *report_string; /* Formatted ready for display */ const void *sort_value; /* Raw value for sorting */};struct row { struct list list; struct dm_report *rh; struct list fields; /* Fields in display order */ struct dm_report_field *(*sort_fields)[]; /* Fields in sort order */};static const struct dm_report_object_type *_find_type(struct dm_report *rh, uint32_t report_type){ const struct dm_report_object_type *t; for (t = rh->types; t->data_fn; t++) if (t->id == report_type) return t; return NULL;}/* * Data-munging functions to prepare each data type for display and sorting */int dm_report_field_string(struct dm_report *rh, struct dm_report_field *field, const char **data){ char *repstr; if (!(repstr = dm_pool_strdup(rh->mem, *data))) { log_error("dm_report_field_string: dm_pool_strdup failed"); return 0; } field->report_string = repstr; field->sort_value = (const void *) field->report_string; return 1;}int dm_report_field_int(struct dm_report *rh, struct dm_report_field *field, const int *data){ const int value = *data; uint64_t *sortval; char *repstr; if (!(repstr = dm_pool_zalloc(rh->mem, 13))) { log_error("dm_report_field_int: dm_pool_alloc failed"); return 0; } if (!(sortval = dm_pool_alloc(rh->mem, sizeof(int64_t)))) { log_error("dm_report_field_int: dm_pool_alloc failed"); return 0; } if (dm_snprintf(repstr, 12, "%d", value) < 0) { log_error("dm_report_field_int: int too big: %d", value); return 0; } *sortval = (const uint64_t) value; field->sort_value = sortval; field->report_string = repstr; return 1;}int dm_report_field_uint32(struct dm_report *rh, struct dm_report_field *field, const uint32_t *data){ const uint32_t value = *data; uint64_t *sortval; char *repstr; if (!(repstr = dm_pool_zalloc(rh->mem, 12))) { log_error("dm_report_field_uint32: dm_pool_alloc failed"); return 0; } if (!(sortval = dm_pool_alloc(rh->mem, sizeof(uint64_t)))) { log_error("dm_report_field_uint32: dm_pool_alloc failed"); return 0; } if (dm_snprintf(repstr, 11, "%u", value) < 0) { log_error("dm_report_field_uint32: uint32 too big: %u", value); return 0; } *sortval = (const uint64_t) value; field->sort_value = sortval; field->report_string = repstr; return 1;}int dm_report_field_int32(struct dm_report *rh, struct dm_report_field *field, const int32_t *data){ const int32_t value = *data; uint64_t *sortval; char *repstr; if (!(repstr = dm_pool_zalloc(rh->mem, 13))) { log_error("dm_report_field_int32: dm_pool_alloc failed"); return 0; } if (!(sortval = dm_pool_alloc(rh->mem, sizeof(int64_t)))) { log_error("dm_report_field_int32: dm_pool_alloc failed"); return 0; } if (dm_snprintf(repstr, 12, "%d", value) < 0) { log_error("dm_report_field_int32: int32 too big: %d", value); return 0; } *sortval = (const uint64_t) value; field->sort_value = sortval; field->report_string = repstr; return 1;}int dm_report_field_uint64(struct dm_report *rh, struct dm_report_field *field, const uint64_t *data){ const int value = *data; uint64_t *sortval; char *repstr; if (!(repstr = dm_pool_zalloc(rh->mem, 22))) { log_error("dm_report_field_uint64: dm_pool_alloc failed"); return 0; } if (!(sortval = dm_pool_alloc(rh->mem, sizeof(uint64_t)))) { log_error("dm_report_field_uint64: dm_pool_alloc failed"); return 0; } if (dm_snprintf(repstr, 21, "%d", value) < 0) { log_error("dm_report_field_uint64: uint64 too big: %d", value); return 0; } *sortval = (const uint64_t) value; field->sort_value = sortval; field->report_string = repstr; return 1;}/* * Helper functions for custom report functions */void dm_report_field_set_value(struct dm_report_field *field, const void *value, const void *sortvalue){ field->report_string = (const char *) value; field->sort_value = sortvalue ? : value;}/* * show help message */static void _display_fields(struct dm_report *rh){ uint32_t f; const struct dm_report_object_type *type; const char *desc, *last_desc = ""; size_t id_len = 0; for (f = 0; rh->fields[f].report_fn; f++) if (strlen(rh->fields[f].id) > id_len) id_len = strlen(rh->fields[f].id); for (f = 0; rh->fields[f].report_fn; f++) { if ((type = _find_type(rh, rh->fields[f].type)) && type->desc) desc = type->desc; else desc = " "; if (desc != last_desc) { if (*last_desc) log_print(" "); log_print("%s Fields", desc); log_print("%*.*s", (int) strlen(desc) + 7, (int) strlen(desc) + 7, "------------------------------------------"); } /* FIXME Add line-wrapping at terminal width (or 80 cols) */ log_print(" %-*s - %s", (int) id_len, rh->fields[f].id, rh->fields[f].desc); last_desc = desc; }}/* * Initialise report handle */static int _copy_field(struct dm_report *rh, struct field_properties *dest, uint32_t field_num){ dest->field_num = field_num; dest->width = rh->fields[field_num].width; dest->flags = rh->fields[field_num].flags & DM_REPORT_FIELD_MASK; /* set object type method */ dest->type = _find_type(rh, rh->fields[field_num].type); if (!dest->type) { log_error("dm_report: field not match: %s", rh->fields[field_num].id); return 0; } return 1;}static struct field_properties * _add_field(struct dm_report *rh, uint32_t field_num, uint32_t flags){ struct field_properties *fp; rh->report_types |= rh->fields[field_num].type; if (!(fp = dm_pool_zalloc(rh->mem, sizeof(struct field_properties)))) { log_error("dm_report: struct field_properties allocation " "failed"); return NULL; } if (!_copy_field(rh, fp, field_num)) { stack; dm_pool_free(rh->mem, fp); return NULL; } fp->flags |= flags; /* * Place hidden fields at the front so list_end() will * tell us when we've reached the last visible field. */ if (fp->flags & FLD_HIDDEN) list_add_h(&rh->field_props, &fp->list); else list_add(&rh->field_props, &fp->list); return fp;}/* * Compare name1 against name2 or prefix plus name2 * name2 is not necessarily null-terminated. * len2 is the length of name2. */static int _is_same_field(const char *name1, const char *name2, size_t len2, const char *prefix){ size_t prefix_len; /* Exact match? */ if (!strncasecmp(name1, name2, len2) && strlen(name1) == len2) return 1; /* Match including prefix? */ prefix_len = strlen(prefix); if (!strncasecmp(prefix, name1, prefix_len) && !strncasecmp(name1 + prefix_len, name2, len2) && strlen(name1) == prefix_len + len2) return 1; return 0;}static int _field_match(struct dm_report *rh, const char *field, size_t flen){ uint32_t f; if (!flen) return 0; for (f = 0; rh->fields[f].report_fn; f++) if (_is_same_field(rh->fields[f].id, field, flen, rh->field_prefix)) return _add_field(rh, f, 0) ? 1 : 0; return 0;}static int _add_sort_key(struct dm_report *rh, uint32_t field_num, uint32_t flags){ struct field_properties *fp, *found = NULL; list_iterate_items(fp, &rh->field_props) { if (fp->field_num == field_num) { found = fp; break; } } if (!found && !(found = _add_field(rh, field_num, FLD_HIDDEN))) return_0; if (found->flags & FLD_SORT_KEY) { log_error("dm_report: Ignoring duplicate sort field: %s", rh->fields[field_num].id); return 1; } found->flags |= FLD_SORT_KEY; found->sort_posn = rh->keys_count++; found->flags |= flags; return 1;}static int _key_match(struct dm_report *rh, const char *key, size_t len){ uint32_t f; uint32_t flags; if (!len) return 0; if (*key == '+') { key++; len--; flags = FLD_ASCENDING; } else if (*key == '-') { key++; len--; flags = FLD_DESCENDING; } else flags = FLD_ASCENDING; if (!len) { log_error("dm_report: Missing sort field name"); return 0; } for (f = 0; rh->fields[f].report_fn; f++) if (_is_same_field(rh->fields[f].id, key, len, rh->field_prefix)) return _add_sort_key(rh, f, flags); return 0;}static int _parse_options(struct dm_report *rh, const char *format){ const char *ws; /* Word start */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -