예제 #1
0
static struct libscols_line *get_line_with_id(struct libscols_table *tb,
						int col_id, const char *id)
{
	struct libscols_line *ln;
	struct libscols_iter *itr = scols_new_iter(SCOLS_ITER_FORWARD);

	while (scols_table_next_line(tb, itr, &ln) == 0) {
		struct libscols_cell *ce = scols_line_get_cell(ln, col_id);
		const char *data = ce ? scols_cell_get_data(ce) : NULL;

		if (data && strcmp(data, id) == 0)
			break;
	}

	scols_free_iter(itr);
	return ln;
}
예제 #2
0
static void compose_tree(struct libscols_table *tb, int parent_col, int id_col)
{
	struct libscols_line *ln;
	struct libscols_iter *itr = scols_new_iter(SCOLS_ITER_FORWARD);

	while (scols_table_next_line(tb, itr, &ln) == 0) {
		struct libscols_line *parent = NULL;
		struct libscols_cell *ce = scols_line_get_cell(ln, parent_col);
		const char *data = ce ? scols_cell_get_data(ce) : NULL;

		if (data)
			parent = get_line_with_id(tb, id_col, data);
		if (parent)
			scols_line_add_child(parent, ln);
	}

	scols_free_iter(itr);
}
예제 #3
0
/* It would be possible to use fdisk_table_to_string(), but we want some
 * extension to the output format, so let's do it without libfdisk
 */
static char *table_to_string(struct cfdisk *cf, struct fdisk_table *tb)
{
	const struct fdisk_column *col;
	struct fdisk_partition *pa;
	struct fdisk_label *lb;
	struct fdisk_iter *itr = NULL;
	struct libscols_table *table = NULL;
	struct libscols_iter *s_itr = NULL;
	char *res = NULL;
	size_t i;
	int tree = 0;
	struct libscols_line *ln, *ln_cont = NULL;

	DBG(FRONTEND, ul_debug("table: convert to string"));

	assert(cf);
	assert(cf->cxt);
	assert(cf->cols);
	assert(tb);

	lb = fdisk_context_get_label(cf->cxt, NULL);
	assert(lb);

	itr = fdisk_new_iter(FDISK_ITER_FORWARD);
	if (!itr)
		goto done;

	/* get container (e.g. extended partition) */
	while (fdisk_table_next_partition(tb, itr, &pa) == 0) {
		if (fdisk_partition_is_nested(pa)) {
			DBG(FRONTEND, ul_debug("table: nested detected, using tree"));
			tree = SCOLS_FL_TREE;
			break;
		}
	}

	table = scols_new_table();
	if (!table)
		goto done;
	scols_table_enable_maxout(table, 1);

	/* headers */
	for (i = 0; i < cf->ncols; i++) {
		col = fdisk_label_get_column(lb, cf->cols[i]);
		if (col) {
			int fl = col->scols_flags;
			if (tree && col->id == FDISK_COL_DEVICE)
				fl |= SCOLS_FL_TREE;
			if (!scols_table_new_column(table, col->name, col->width, fl))
				goto done;
		}
	}

	/* data */
	fdisk_reset_iter(itr, FDISK_ITER_FORWARD);

	while (fdisk_table_next_partition(tb, itr, &pa) == 0) {
		struct libscols_line *parent = fdisk_partition_is_nested(pa) ? ln_cont : NULL;

		ln = scols_table_new_line(table, parent);
		if (!ln)
			goto done;
		for (i = 0; i < cf->ncols; i++) {
			char *cdata = NULL;
			col = fdisk_label_get_column(lb, cf->cols[i]);
			if (!col)
				continue;
			if (fdisk_partition_to_string(pa, cf->cxt, col->id, &cdata))
				continue;
			scols_line_refer_data(ln, i, cdata);
		}
		if (tree && fdisk_partition_is_container(pa))
			ln_cont = ln;

		scols_line_set_userdata(ln, (void *) pa);
		fdisk_ref_partition(pa);
	}

	if (scols_table_is_empty(table))
		goto done;

	scols_table_reduce_termwidth(table, ARROW_CURSOR_WIDTH);
	scols_print_table_to_string(table, &res);

	/* scols_* code might reorder lines, let's reorder @tb according to the
	 * final output (it's no problem because partitions are addressed by
	 * parno stored within struct fdisk_partition)  */

	/* remove all */
	fdisk_reset_iter(itr, FDISK_ITER_FORWARD);
	while (fdisk_table_next_partition(tb, itr, &pa) == 0)
		fdisk_table_remove_partition(tb, pa);

	s_itr = scols_new_iter(SCOLS_ITER_FORWARD);
	if (!s_itr)
		goto done;

	/* add all in the right order (don't forget the output is tree) */
	while (scols_table_next_line(table, s_itr, &ln) == 0) {
		if (scols_line_get_parent(ln))
			continue;
		if (partition_from_scols(tb, ln))
			break;
	}
done:
	scols_unref_table(table);
	scols_free_iter(s_itr);
	fdisk_free_iter(itr);

	return res;
}
예제 #4
0
/*
 * This function counts column width.
 *
 * For the SCOLS_FL_NOEXTREMES columns it is possible to call this function
 * two times. The first pass counts the width and average width. If the column
 * contains fields that are too large (a width greater than 2 * average) then
 * the column is marked as "extreme". In the second pass all extreme fields
 * are ignored and the column width is counted from non-extreme fields only.
 */
static int count_column_width(struct libscols_table *tb,
			      struct libscols_column *cl,
			      struct libscols_buffer *buf)
{
	int rc = 0, no_header = 0;

	assert(tb);
	assert(cl);

	cl->width = 0;
	if (!cl->width_min) {
		if (cl->width_hint < 1 && scols_table_is_maxout(tb) && tb->is_term) {
			cl->width_min = (size_t) (cl->width_hint * tb->termwidth);
			if (cl->width_min && !is_last_column(cl))
				cl->width_min--;
		}
		if (scols_cell_get_data(&cl->header)) {
			size_t len = mbs_safe_width(scols_cell_get_data(&cl->header));
			cl->width_min = max(cl->width_min, len);
		} else
			no_header = 1;

		if (!cl->width_min)
			cl->width_min = 1;
	}

	if (scols_table_is_tree(tb)) {
		/* Count width for tree */
		rc = scols_walk_tree(tb, cl, walk_count_cell_width, (void *) buf);
		if (rc)
			goto done;
	} else {
		/* Count width for list */
		struct libscols_iter itr;
		struct libscols_line *ln;

		scols_reset_iter(&itr, SCOLS_ITER_FORWARD);
		while (scols_table_next_line(tb, &itr, &ln) == 0) {
			rc = count_cell_width(tb, ln, cl, buf);
			if (rc)
				goto done;
		}
	}

	if (scols_column_is_tree(cl) && has_groups(tb)) {
		/* We don't fill buffer with groups tree ascii art during width
		 * calcualtion. The print function only enlarge grpset[] and we
		 * calculate final width from grpset_size.
		 */
		size_t gprwidth = tb->grpset_size + 1;
		cl->width_treeart += gprwidth;
		cl->width_max += gprwidth;
		cl->width += gprwidth;
		if (cl->extreme_count)
			cl->extreme_sum += gprwidth;
	}

	if (cl->extreme_count && cl->width_avg == 0) {
		cl->width_avg = cl->extreme_sum / cl->extreme_count;
		if (cl->width_avg && cl->width_max > cl->width_avg * 2)
			cl->is_extreme = 1;
	}

	/* enlarge to minimal width */
	if (cl->width < cl->width_min && !scols_column_is_strict_width(cl))
		cl->width = cl->width_min;

	/* use absolute size for large columns */
	else if (cl->width_hint >= 1 && cl->width < (size_t) cl->width_hint
		 && cl->width_min < (size_t) cl->width_hint)

		cl->width = (size_t) cl->width_hint;


	/* Column without header and data, set minimal size to zero (default is 1) */
	if (cl->width_max == 0 && no_header && cl->width_min == 1 && cl->width <= 1)
		cl->width = cl->width_min = 0;

done:
	ON_DBG(COL, dbg_column(tb, cl));
	return rc;
}