/*
* 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
*/
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;
/* 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;
}
/*
* Place hidden fields at the front so dm_list_end() will
* tell us when we've reached the last visible field.
*/
if (fp->flags & FLD_HIDDEN)
dm_list_add_h(&rh->field_props, &fp->list);
else
dm_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;
/*
* rh->report_types is updated in _parse_fields() and _parse_keys()
* to contain all types corresponding to the fields specified by
* fields or keys.
*/
if (report_types)
rh->report_types = *report_types;
/* With columns_as_rows we must buffer and not align. */
if (output_flags & DM_REPORT_OUTPUT_COLUMNS_AS_ROWS) {
if (!(output_flags & DM_REPORT_OUTPUT_BUFFERED))
rh->flags |= DM_REPORT_OUTPUT_BUFFERED;
if (output_flags & DM_REPORT_OUTPUT_ALIGNED)
rh->flags &= ~DM_REPORT_OUTPUT_ALIGNED;
}
if (output_flags & DM_REPORT_OUTPUT_BUFFERED)
rh->flags |= RH_SORT_REQUIRED;
if (!(rh->mem = dm_pool_create("report", 10 * 1024))) {
log_error("dm_report_init: allocation of memory pool failed");
dm_free(rh);
return NULL;
}
/*
* To keep the code needed to add the "all" field to a minimum, we parse
* the field lists twice. The first time we only update the report type.
* FIXME Use one pass instead and expand the "all" field afterwards.
*/
if (!_parse_fields(rh, output_fields, 1) ||
!_parse_keys(rh, sort_keys, 1)) {
dm_report_free(rh);
return NULL;
}
/* Generate list of fields for output based on format string & flags */
if (!_parse_fields(rh, output_fields, 0) ||
!_parse_keys(rh, sort_keys, 0)) {
dm_report_free(rh);
return NULL;
}
/* Return updated types value for further compatility check by caller */
if (report_types)
*report_types = rh->report_types;
/* For each field to be displayed, call its report_fn */
dm_list_iterate_items(fp, &rh->field_props) {
if (!(field = dm_pool_zalloc(rh->mem, sizeof(*field)))) {
log_error("dm_report_object: "
"struct dm_report_field allocation failed");
return 0;
}
field->props = fp;
data = _report_get_field_data(rh, fp, object);
if (!data)
return 0;
if (!rh->fields[fp->field_num].report_fn(rh, rh->mem,
field, data,
rh->private)) {
log_error("dm_report_object: "
"report function failed for field %s",
rh->fields[fp->field_num].id);
return 0;
}
if ((strlen(field->report_string) > field->props->width))
field->props->width = strlen(field->report_string);
if (rh->flags & DM_REPORT_OUTPUT_FIELD_NAME_PREFIX) {
if (!(field_id = strdup(rh->fields[field->props->field_num].id))) {
log_error("dm_report: Failed to copy field name");
return 0;
}
if (!dm_pool_grow_object(rh->mem, rh->output_field_name_prefix, 0)) {
log_error("dm_report: Unable to extend output line");
return 0;
}
if (!dm_pool_grow_object(rh->mem, _toupperstr(field_id), 0)) {
log_error("dm_report: Unable to extend output line");
return 0;
}
free(field_id);
if (!dm_pool_grow_object(rh->mem, "=", 1)) {
log_error("dm_report: Unable to extend output line");
return 0;
}
if (!(rh->flags & DM_REPORT_OUTPUT_FIELD_UNQUOTED) &&
!dm_pool_grow_object(rh->mem, "\'", 1)) {
log_error("dm_report: Unable to extend output line");
return 0;
}
}
repstr = field->report_string;
width = field->props->width;
if (!(rh->flags & DM_REPORT_OUTPUT_ALIGNED)) {
if (!dm_pool_grow_object(rh->mem, repstr, 0)) {
log_error("dm_report: Unable to extend output line");
return 0;
}
} else {
if (!(align = field->props->flags & DM_REPORT_FIELD_ALIGN_MASK))
align = (field->props->flags & DM_REPORT_FIELD_TYPE_NUMBER) ?
DM_REPORT_FIELD_ALIGN_RIGHT : DM_REPORT_FIELD_ALIGN_LEFT;
if (align & DM_REPORT_FIELD_ALIGN_LEFT) {
if (dm_snprintf(buf, sizeof(buf), "%-*.*s",
width, width, repstr) < 0) {
log_error("dm_report: left-aligned snprintf() failed");
return 0;
}
if (!dm_pool_grow_object(rh->mem, buf, width)) {
log_error("dm_report: Unable to extend output line");
return 0;
}
} else if (align & DM_REPORT_FIELD_ALIGN_RIGHT) {
if (dm_snprintf(buf, sizeof(buf), "%*.*s",
width, width, repstr) < 0) {
log_error("dm_report: right-aligned snprintf() failed");
return 0;
}
if (!dm_pool_grow_object(rh->mem, buf, width)) {
log_error("dm_report: Unable to extend output line");
return 0;
}
}
}
if ((rh->flags & DM_REPORT_OUTPUT_FIELD_NAME_PREFIX) &&
!(rh->flags & DM_REPORT_OUTPUT_FIELD_UNQUOTED))
if (!dm_pool_grow_object(rh->mem, "\'", 1)) {
log_error("dm_report: Unable to extend output line");
return 0;
}
if (!dm_pool_begin_object(rh->mem, 512)) {
log_error("dm_report: Unable to allocate output line");
return 0;
}
dm_list_iterate_items(fp, &rh->field_props) {
if (fp->flags & FLD_HIDDEN) {
dm_list_iterate_items(row, &rh->rows) {
field = dm_list_item(dm_list_first(&row->fields), struct dm_report_field);
dm_list_del(&field->list);
}
continue;
}
if ((rh->flags & DM_REPORT_OUTPUT_HEADINGS)) {
if (!dm_pool_grow_object(rh->mem, rh->fields[fp->field_num].heading, 0)) {
log_error("dm_report: Failed to extend row for field name");
goto bad;
}
if (!dm_pool_grow_object(rh->mem, rh->separator, 0)) {
log_error("dm_report: Failed to extend row with separator");
goto bad;
}
}
dm_list_iterate_items(row, &rh->rows) {
if ((field = dm_list_item(dm_list_first(&row->fields), struct dm_report_field))) {
if (!_output_field(rh, field))
goto bad;
dm_list_del(&field->list);
}
if (!dm_list_end(&rh->rows, &row->list))
if (!dm_pool_grow_object(rh->mem, rh->separator, 0)) {
log_error("dm_report: Unable to extend output line");
goto bad;
}
}
if (!dm_pool_grow_object(rh->mem, "\0", 1)) {
log_error("dm_report: Failed to terminate row");
goto bad;
}
log_print("%s", (char *) dm_pool_end_object(rh->mem));
}