Exemplo n.º 1
0
/**
 * mnt_init_debug:
 * @mask: debug mask (0xffff to enable full debugging)
 *
 * If the @mask is not specified, then this function reads
 * the LIBMOUNT_DEBUG environment variable to get the mask.
 *
 * Already initialized debugging stuff cannot be changed. Calling
 * this function twice has no effect.
 */
void mnt_init_debug(int mask)
{
	if (libmount_debug_mask)
		return;

	__UL_INIT_DEBUG(libmount, MNT_DEBUG_, mask, LIBMOUNT_DEBUG);

	if (libmount_debug_mask != MNT_DEBUG_INIT
	    && libmount_debug_mask != (MNT_DEBUG_HELP|MNT_DEBUG_INIT)) {
		const char *ver = NULL;
		const char **features = NULL, **p;

		mnt_get_library_version(&ver);
		mnt_get_library_features(&features);

		DBG(INIT, ul_debug("library debug mask: 0x%04x", libmount_debug_mask));
		DBG(INIT, ul_debug("library version: %s", ver));
		p = features;
		while (p && *p)
			DBG(INIT, ul_debug("    feature: %s", *p++));
	}

	ON_DBG(HELP, ul_debug_print_masks("LIBMOUNT_DEBUG",
				UL_DEBUG_MASKNAMES(libmount)));
}
Exemplo n.º 2
0
/**
 * blkid_init_debug:
 * @mask: debug mask (0xffff to enable full debugging)
 *
 * If the @mask is not specified then this function reads
 * LIBBLKID_DEBUG environment variable to get the mask.
 *
 * Already initialized debugging stuff cannot be changed. It does not
 * have effect to call this function twice.
 */
void blkid_init_debug(int mask)
{
	if (libblkid_debug_mask)
		return;

	__UL_INIT_DEBUG(libblkid, BLKID_DEBUG_, mask, LIBBLKID_DEBUG);

	if (libblkid_debug_mask != BLKID_DEBUG_INIT
	    && libblkid_debug_mask != (BLKID_DEBUG_HELP|BLKID_DEBUG_INIT)) {
		const char *ver = NULL;
		const char *date = NULL;

		blkid_get_library_version(&ver, &date);
		DBG(INIT, ul_debug("library debug mask: 0x%04x", libblkid_debug_mask));
		DBG(INIT, ul_debug("library version: %s [%s]", ver, date));

	}
	ON_DBG(HELP, ul_debug_print_masks("LIBBLKID_DEBUG",
				UL_DEBUG_MASKNAMES(libblkid)));
}
Exemplo n.º 3
0
/**
 * scols_new_table:
 *
 * Returns: A newly allocated table.
 */
struct libscols_table *scols_new_table(void)
{
	struct libscols_table *tb;

	tb = calloc(1, sizeof(struct libscols_table));
	if (!tb)
		return NULL;

	tb->refcount = 1;
	tb->out = stdout;
	tb->termwidth = get_terminal_width(80);

	INIT_LIST_HEAD(&tb->tb_lines);
	INIT_LIST_HEAD(&tb->tb_columns);

	DBG(TAB, ul_debugobj(tb, "alloc"));
	ON_DBG(INIT, check_padding_debug(tb));

	return tb;
}
Exemplo n.º 4
0
int mnt_context_setup_loopdev(struct libmnt_context *cxt)
{
	const char *backing_file, *optstr, *loopdev = NULL;
	char *val = NULL;
	size_t len;
	struct loopdev_cxt lc;
	int rc = 0, lo_flags = 0;
	uint64_t offset = 0, sizelimit = 0;

	assert(cxt->fs);
	assert((cxt->flags & MNT_FL_MOUNTFLAGS_MERGED));

	if (!cxt)
		return -EINVAL;

	backing_file = mnt_fs_get_srcpath(cxt->fs);
	if (!backing_file)
		return -EINVAL;

	DBG(CXT, ul_debugobj(cxt, "trying to setup loopdev for %s", backing_file));

	if (cxt->mountflags & MS_RDONLY) {
		DBG(CXT, ul_debugobj(cxt, "enabling READ-ONLY flag"));
		lo_flags |= LO_FLAGS_READ_ONLY;
	}

	rc = loopcxt_init(&lc, 0);
	if (rc)
		return rc;

	ON_DBG(CXT, loopcxt_enable_debug(&lc, 1));

	optstr = mnt_fs_get_user_options(cxt->fs);

	/*
	 * loop=
	 */
	if (rc == 0 && (cxt->user_mountflags & MNT_MS_LOOP) &&
	    mnt_optstr_get_option(optstr, "loop", &val, &len) == 0 && val) {

		val = strndup(val, len);
		rc = val ? loopcxt_set_device(&lc, val) : -ENOMEM;
		free(val);

		if (rc == 0)
			loopdev = loopcxt_get_device(&lc);
	}

	/*
	 * offset=
	 */
	if (rc == 0 && (cxt->user_mountflags & MNT_MS_OFFSET) &&
	    mnt_optstr_get_option(optstr, "offset", &val, &len) == 0) {
		rc = mnt_parse_offset(val, len, &offset);
		if (rc) {
			DBG(CXT, ul_debugobj(cxt, "failed to parse offset="));
			rc = -MNT_ERR_MOUNTOPT;
		}
	}

	/*
	 * sizelimit=
	 */
	if (rc == 0 && (cxt->user_mountflags & MNT_MS_SIZELIMIT) &&
	    mnt_optstr_get_option(optstr, "sizelimit", &val, &len) == 0) {
		rc = mnt_parse_offset(val, len, &sizelimit);
		if (rc) {
			DBG(CXT, ul_debugobj(cxt, "failed to parse sizelimit="));
			rc = -MNT_ERR_MOUNTOPT;
		}
	}

	/*
	 * encryption=
	 */
	if (rc == 0 && (cxt->user_mountflags & MNT_MS_ENCRYPTION) &&
	    mnt_optstr_get_option(optstr, "encryption", &val, &len) == 0) {
		DBG(CXT, ul_debugobj(cxt, "encryption no longer supported"));
		rc = -MNT_ERR_MOUNTOPT;
	}

	if (rc == 0 && is_mounted_same_loopfile(cxt,
				mnt_context_get_target(cxt),
				backing_file, offset))
		rc = -EBUSY;

	if (rc)
		goto done;

	/* since 2.6.37 we don't have to store backing filename to mtab
	 * because kernel provides the name in /sys.
	 */
	if (get_linux_version() >= KERNEL_VERSION(2, 6, 37) ||
	    !mnt_context_mtab_writable(cxt)) {
		DBG(CXT, ul_debugobj(cxt, "enabling AUTOCLEAR flag"));
		lo_flags |= LO_FLAGS_AUTOCLEAR;
	}

	do {
		/* found free device */
		if (!loopdev) {
			rc = loopcxt_find_unused(&lc);
			if (rc)
				goto done;
			DBG(CXT, ul_debugobj(cxt, "trying to use %s",
						loopcxt_get_device(&lc)));
		}

		/* set device attributes
		 * -- note that loopcxt_find_unused() resets "lc"
		 */
		rc = loopcxt_set_backing_file(&lc, backing_file);

		if (!rc && offset)
			rc = loopcxt_set_offset(&lc, offset);
		if (!rc && sizelimit)
			rc = loopcxt_set_sizelimit(&lc, sizelimit);
		if (!rc)
			loopcxt_set_flags(&lc, lo_flags);
		if (rc) {
			DBG(CXT, ul_debugobj(cxt, "failed to set loopdev attributes"));
			goto done;
		}

		/* setup the device */
		rc = loopcxt_setup_device(&lc);
		if (!rc)
			break;		/* success */

		if (loopdev || rc != -EBUSY) {
			DBG(CXT, ul_debugobj(cxt, "failed to setup device"));
			rc = -MNT_ERR_LOOPDEV;
			goto done;
		}
		DBG(CXT, ul_debugobj(cxt, "loopdev stolen...trying again"));
	} while (1);

	if (!rc)
		rc = mnt_fs_set_source(cxt->fs, loopcxt_get_device(&lc));

	if (!rc) {
		/* success */
		cxt->flags |= MNT_FL_LOOPDEV_READY;

		if ((cxt->user_mountflags & MNT_MS_LOOP) &&
		    loopcxt_is_autoclear(&lc)) {
			/*
			 * autoclear flag accepted by the kernel, don't store
			 * the "loop=" option to mtab.
			 */
			cxt->user_mountflags &= ~MNT_MS_LOOP;
			mnt_optstr_remove_option(&cxt->fs->user_optstr, "loop");
		}

		if (!(cxt->mountflags & MS_RDONLY) &&
		    loopcxt_is_readonly(&lc))
			/*
			 * mount planned read-write, but loopdev is read-only,
			 * let's fix mount options...
			 */
			mnt_context_set_mflags(cxt, cxt->mountflags | MS_RDONLY);

		/* we have to keep the device open until mount(1),
		 * otherwise it will be auto-cleared by kernel
		 */
		cxt->loopdev_fd = loopcxt_get_fd(&lc);
		loopcxt_set_fd(&lc, -1, 0);
	}
done:
	loopcxt_deinit(&lc);
	return rc;
}
Exemplo n.º 5
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;
}
Exemplo n.º 6
0
/*
 * This is core of the scols_* voodoo...
 */
int __scols_calculate(struct libscols_table *tb, struct libscols_buffer *buf)
{
	struct libscols_column *cl;
	struct libscols_iter itr;
	size_t width = 0, width_min = 0;	/* output width */
	int stage, rc = 0;
	int extremes = 0, group_ncolumns = 0;
	size_t colsepsz;


	DBG(TAB, ul_debugobj(tb, "-----calculate-(termwidth=%zu)-----", tb->termwidth));
	tb->is_dummy_print = 1;

	colsepsz = mbs_safe_width(colsep(tb));

	if (has_groups(tb))
		group_ncolumns = 1;

	/* set basic columns width
	 */
	scols_reset_iter(&itr, SCOLS_ITER_FORWARD);
	while (scols_table_next_column(tb, &itr, &cl) == 0) {
		int is_last;

		if (scols_column_is_hidden(cl))
			continue;

		/* we print groups chart only for the for the first tree column */
		if (scols_column_is_tree(cl) && group_ncolumns == 1) {
			cl->is_groups = 1;
			group_ncolumns++;
		}

		rc = count_column_width(tb, cl, buf);
		if (rc)
			goto done;

		is_last = is_last_column(cl);

		width += cl->width + (is_last ? 0 : colsepsz);		/* separator for non-last column */
		width_min += cl->width_min + (is_last ? 0 : colsepsz);
		if (cl->is_extreme)
			extremes++;
	}

	if (!tb->is_term) {
		DBG(TAB, ul_debugobj(tb, " non-terminal output"));
		goto done;
	}

	/* be paranoid */
	if (width_min > tb->termwidth && scols_table_is_maxout(tb)) {
		DBG(TAB, ul_debugobj(tb, " min width larger than terminal! [width=%zu, term=%zu]", width_min, tb->termwidth));

		scols_reset_iter(&itr, SCOLS_ITER_FORWARD);
		while (width_min > tb->termwidth
		       && scols_table_next_column(tb, &itr, &cl) == 0) {
			if (scols_column_is_hidden(cl))
				continue;
			width_min--;
			cl->width_min--;
		}
		DBG(TAB, ul_debugobj(tb, " min width reduced to %zu", width_min));
	}

	/* reduce columns with extreme fields */
	if (width > tb->termwidth && extremes) {
		DBG(TAB, ul_debugobj(tb, " reduce width (extreme columns)"));

		scols_reset_iter(&itr, SCOLS_ITER_FORWARD);
		while (scols_table_next_column(tb, &itr, &cl) == 0) {
			size_t org_width;

			if (!cl->is_extreme || scols_column_is_hidden(cl))
				continue;

			org_width = cl->width;
			rc = count_column_width(tb, cl, buf);
			if (rc)
				goto done;

			if (org_width > cl->width)
				width -= org_width - cl->width;
			else
				extremes--;	/* hmm... nothing reduced */
		}
	}

	if (width < tb->termwidth) {
		if (extremes) {
			DBG(TAB, ul_debugobj(tb, " enlarge width (extreme columns)"));

			/* enlarge the first extreme column */
			scols_reset_iter(&itr, SCOLS_ITER_FORWARD);
			while (scols_table_next_column(tb, &itr, &cl) == 0) {
				size_t add;

				if (!cl->is_extreme || scols_column_is_hidden(cl))
					continue;

				/* this column is too large, ignore?
				if (cl->width_max - cl->width >
						(tb->termwidth - width))
					continue;
				*/

				add = tb->termwidth - width;
				if (add && cl->width + add > cl->width_max)
					add = cl->width_max - cl->width;

				cl->width += add;
				width += add;

				if (width == tb->termwidth)
					break;
			}
		}

		if (width < tb->termwidth && scols_table_is_maxout(tb)) {
			DBG(TAB, ul_debugobj(tb, " enlarge width (max-out)"));

			/* try enlarging all columns */
			while (width < tb->termwidth) {
				scols_reset_iter(&itr, SCOLS_ITER_FORWARD);
				while (scols_table_next_column(tb, &itr, &cl) == 0) {
					if (scols_column_is_hidden(cl))
						continue;
					cl->width++;
					width++;
					if (width == tb->termwidth)
						break;
				}
			}
		} else if (width < tb->termwidth) {
			/* enlarge the last column */
			struct libscols_column *col = list_entry(
				tb->tb_columns.prev, struct libscols_column, cl_columns);

			DBG(TAB, ul_debugobj(tb, " enlarge width (last column)"));

			if (!scols_column_is_right(col) && tb->termwidth - width > 0) {
				col->width += tb->termwidth - width;
				width = tb->termwidth;
			}
		}
	}

	/* bad, we have to reduce output width, this is done in three stages:
	 *
	 * 1) trunc relative with trunc flag if the column width is greater than
	 *    expected column width (it means "width_hint * terminal_width").
	 *
	 * 2) trunc all with trunc flag
	 *
	 * 3) trunc relative without trunc flag
	 *
	 * Note that SCOLS_FL_WRAP (if no custom wrap function is specified) is
	 * interpreted as SCOLS_FL_TRUNC.
	 */
	for (stage = 1; width > tb->termwidth && stage <= 3; ) {
		size_t org_width = width;

		DBG(TAB, ul_debugobj(tb, " reduce width - #%d stage (current=%zu, wanted=%zu)",
				stage, width, tb->termwidth));

		scols_reset_iter(&itr, SCOLS_ITER_FORWARD);
		while (scols_table_next_column(tb, &itr, &cl) == 0) {

			int trunc_flag = 0;

			DBG(TAB, ul_debugobj(cl, "   checking %s (width=%zu, treeart=%zu)",
						cl->header.data, cl->width, cl->width_treeart));
			if (scols_column_is_hidden(cl))
				continue;
			if (width <= tb->termwidth)
				break;

			/* never truncate if already minimal width */
			if (cl->width == cl->width_min)
				continue;

			/* never truncate the tree */
			if (scols_column_is_tree(cl) && width <= cl->width_treeart)
				continue;

			/* nothing to truncate */
			if (cl->width == 0 || width == 0)
				continue;

			trunc_flag = scols_column_is_trunc(cl)
				    || (scols_column_is_wrap(cl) && !scols_column_is_customwrap(cl));

			switch (stage) {
			/* #1 stage - trunc relative with TRUNC flag */
			case 1:
				if (!trunc_flag)		/* ignore: missing flag */
					break;
				if (cl->width_hint <= 0 || cl->width_hint >= 1)	/* ignore: no relative */
					break;
				if (cl->width < (size_t) (cl->width_hint * tb->termwidth)) /* ignore: smaller than expected width */
					break;

				DBG(TAB, ul_debugobj(tb, "     reducing (relative with flag)"));
				cl->width--;
				width--;
				break;

			/* #2 stage - trunc all with TRUNC flag */
			case 2:
				if (!trunc_flag)		/* ignore: missing flag */
					break;

				DBG(TAB, ul_debugobj(tb, "     reducing (all with flag)"));
				cl->width--;
				width--;
				break;

			/* #3 stage - trunc relative without flag */
			case 3:
				if (cl->width_hint <= 0 || cl->width_hint >= 1)	/* ignore: no relative */
					break;

				DBG(TAB, ul_debugobj(tb, "     reducing (relative without flag)"));
				cl->width--;
				width--;
				break;
			}

			/* hide zero width columns */
			if (cl->width == 0)
				cl->flags |= SCOLS_FL_HIDDEN;
		}

		/* the current stage is without effect, go to the next */
		if (org_width == width)
			stage++;
	}

	/* ignore last column(s) or force last column to be truncated if
	 * nowrap mode enabled */
	if (tb->no_wrap && width > tb->termwidth) {
		scols_reset_iter(&itr, SCOLS_ITER_BACKWARD);
		while (scols_table_next_column(tb, &itr, &cl) == 0) {

			if (scols_column_is_hidden(cl))
				continue;
			if (width <= tb->termwidth)
				break;
			if (width - cl->width < tb->termwidth) {
				size_t r =  width - tb->termwidth;

				cl->flags |= SCOLS_FL_TRUNC;
				cl->width -= r;
				width -= r;
			} else {
				cl->flags |= SCOLS_FL_HIDDEN;
				width -= cl->width + colsepsz;
			}
		}
	}
done:
	tb->is_dummy_print = 0;
	DBG(TAB, ul_debugobj(tb, "-----final width: %zu (rc=%d)-----", width, rc));
	ON_DBG(TAB, dbg_columns(tb));

	return rc;
}