Exemple #1
0
/**
 * fdisk_add_partition:
 * @cxt: fdisk context
 * @pa: template for the partition (or NULL)
 * @partno: NULL or returns new partition number
 *
 * If @pa is not specified or any @pa item is missiong the libfdisk will ask by
 * fdisk_ask_ API.
 *
 * Adds a new partition to disklabel.
 *
 * Returns: 0 on success, <0 on error.
 */
int fdisk_add_partition(struct fdisk_context *cxt,
			struct fdisk_partition *pa,
			size_t *partno)
{
	int rc;

	assert(cxt);
	assert(cxt->label);

	if (!cxt || !cxt->label)
		return -EINVAL;
	if (!cxt->label->op->add_part)
		return -ENOSYS;
	if (fdisk_missing_geometry(cxt))
		return -EINVAL;

	if (pa)
		DBG(CXT, ul_debugobj(cxt, "adding new partition %p (start=%ju, end=%ju, size=%ju, "
			    "defaults(start=%s, end=%s, partno=%s)",
			    pa,
			    (uintmax_t) fdisk_partition_get_start(pa),
			    (uintmax_t) fdisk_partition_get_end(pa),
			    (uintmax_t) fdisk_partition_get_size(pa),
			    pa->start_follow_default ? "yes" : "no",
			    pa->end_follow_default ? "yes" : "no",
			    pa->partno_follow_default ? "yes" : "no"));
	else
		DBG(CXT, ul_debugobj(cxt, "adding partition"));

	rc = cxt->label->op->add_part(cxt, pa, partno);

	DBG(CXT, ul_debugobj(cxt, "add partition done (rc=%d)", rc));
	return rc;
}
Exemple #2
0
/**
 * fdisk_set_partition:
 * @cxt: context
 * @partno: partition number (0 is the first partition)
 * @pa: new partition setting
 *
 * Modifies disklabel according to setting with in @pa.
 *
 * Returns: 0 on success, <0 on error.
 */
int fdisk_set_partition(struct fdisk_context *cxt, size_t partno,
			struct fdisk_partition *pa)
{
	struct fdisk_partition *xpa = pa;
	int rc;

	if (!cxt || !cxt->label || !pa)
		return -EINVAL;
	if (!cxt->label->op->set_part)
		return -ENOSYS;

	if (pa->resize || fdisk_partition_has_start(pa) || fdisk_partition_has_size(pa)) {
		xpa = __copy_partition(pa);
		xpa->movestart = 0;
		xpa->resize = 0;
		FDISK_INIT_UNDEF(xpa->size);
		FDISK_INIT_UNDEF(xpa->start);

		rc = recount_resize(cxt, partno, xpa, pa);
		if (rc)
			goto done;
	}

	DBG(CXT, ul_debugobj(cxt, "setting partition %zu %p (start=%ju, end=%ju, size=%ju)",
		    partno, xpa,
		    (uintmax_t) fdisk_partition_get_start(xpa),
		    (uintmax_t) fdisk_partition_get_end(xpa),
		    (uintmax_t) fdisk_partition_get_size(xpa)));

	rc = cxt->label->op->set_part(cxt, partno, xpa);
done:
	if (xpa != pa)
		fdisk_unref_partition(xpa);
	return rc;
}
Exemple #3
0
/**
 * fdisk_set_partition:
 * @cxt: context
 * @partno: partition number (0 is the first partition)
 * @pa: new partition setting
 *
 * Modifies disklabel according to setting with in @pa.
 *
 * Returns: 0 on success, <0 on error.
 */
int fdisk_set_partition(struct fdisk_context *cxt, size_t partno,
			struct fdisk_partition *pa)
{
	if (!cxt || !cxt->label || !pa)
		return -EINVAL;
	if (!cxt->label->op->set_part)
		return -ENOSYS;

	DBG(CXT, ul_debugobj(cxt, "setting partition %zu %p (start=%ju, end=%ju, size=%ju, "
		    "defaults(start=%s, end=%s, partno=%s)",
		    partno, pa,
		    (uintmax_t) fdisk_partition_get_start(pa),
		    (uintmax_t) fdisk_partition_get_end(pa),
		    (uintmax_t) fdisk_partition_get_size(pa),
		    pa->start_follow_default ? "yes" : "no",
		    pa->end_follow_default ? "yes" : "no",
		    pa->partno_follow_default ? "yes" : "no"));

	return cxt->label->op->set_part(cxt, partno, pa);
}
Exemple #4
0
/*
 * Uses template @tpl to recount start and size change of the partition @res. The
 * @tpl->size and @tpl->start are interpreted as relative to the current setting.
 */
static int recount_resize(
			struct fdisk_context *cxt, size_t partno,
			struct fdisk_partition *res, struct fdisk_partition *tpl)
{
	fdisk_sector_t start, size;
	struct fdisk_partition *cur = NULL;
	struct fdisk_table *tb = NULL;
	int rc;

	DBG(PART, ul_debugobj(tpl, "resize requested"));

	FDISK_INIT_UNDEF(start);
	FDISK_INIT_UNDEF(size);

	rc = fdisk_get_partitions(cxt, &tb);
	if (!rc)
		rc = fdisk_get_freespaces(cxt, &tb);
	if (rc)
		return rc;

	cur = fdisk_table_get_partition_by_partno(tb, partno);
	if (!cur) {
		fdisk_unref_table(tb);
		return -EINVAL;
	}

	/* 1a) set new start - change relative to the current on-disk setting */
	if (tpl->movestart && fdisk_partition_has_start(tpl)) {
		start = fdisk_partition_get_start(cur);
		if (tpl->movestart == FDISK_MOVE_DOWN) {
			if (fdisk_partition_get_start(tpl) > start)
				goto erange;
			start -= fdisk_partition_get_start(tpl);
		} else
			start += fdisk_partition_get_start(tpl);

	/* 1b) set new start - absolute number */
	} else if (fdisk_partition_has_start(tpl))
		start = fdisk_partition_get_start(tpl);

	/* 2) verify that start is within the current partition or any freespace area */
	if (!FDISK_IS_UNDEF(start)) {
		struct fdisk_partition *area = resize_get_by_offset(tb, start);
		if (area == cur)
			DBG(PART, ul_debugobj(tpl, "resize: start points to the current partition"));
		else if (area && fdisk_partition_is_freespace(area))
			DBG(PART, ul_debugobj(tpl, "resize: start points to freespace"));
		else if (!area && start >= cxt->first_lba && start < cxt->first_lba + (cxt->grain / cxt->sector_size))
			DBG(PART, ul_debugobj(tpl, "resize: start points before first partition"));
		else
			goto erange;
	} else {
		/* no change, start points to the current partition */
		start = fdisk_partition_get_start(cur);
	}

	/* 3a) set new size -- reduce */
	if (tpl->resize == FDISK_RESIZE_REDUCE && fdisk_partition_has_size(tpl)) {
		DBG(PART, ul_debugobj(tpl, "resize: reduce"));
		size = fdisk_partition_get_size(cur);
		if (fdisk_partition_get_size(tpl) > size)
			goto erange;
		size -= fdisk_partition_get_size(tpl);

	/* 3b) set new size -- enlarge */
	} else if (tpl->resize == FDISK_RESIZE_ENLARGE && fdisk_partition_has_size(tpl)) {
		DBG(PART, ul_debugobj(tpl, "resize: enlarge"));
		size = fdisk_partition_get_size(cur);
		size += fdisk_partition_get_size(tpl);

	/* 3c) set new size -- no size specified, enlarge to all freespace */
	} else if (tpl->resize == FDISK_RESIZE_ENLARGE) {
		DBG(PART, ul_debugobj(tpl, "resize: enlarge to all possible"));
		if (resize_get_last_possible(tb, cur, start, &size))
			goto erange;

	/* 3d) set new size -- absolute number */
	} else if (fdisk_partition_has_size(tpl)) {
		DBG(PART, ul_debugobj(tpl, "resize: new absolute size"));
		size = fdisk_partition_get_size(tpl);
	}

	/* 4) verify that size is within the current partition or next free space */
	if (!FDISK_IS_UNDEF(size)) {
		fdisk_sector_t maxsz;
		if (resize_get_last_possible(tb, cur, start, &maxsz))
			goto erange;
		DBG(PART, ul_debugobj(tpl, "resize: size wanted=%ju, max=%ju",
					(uintmax_t) size, (uintmax_t) maxsz));
		if (size > maxsz)
			goto erange;
	}

	DBG(PART, ul_debugobj(tpl, "resize: SUCCESS: start %ju->%ju; size %ju->%ju",
			(uintmax_t) fdisk_partition_get_start(cur), (uintmax_t) start,
			(uintmax_t) fdisk_partition_get_size(cur), (uintmax_t) size));
	res->start = start;
	res->size = size;
	fdisk_unref_table(tb);
	return 0;
erange:
	DBG(PART, ul_debugobj(tpl, "resize: FAILED"));
	fdisk_warnx(cxt, _("Failed to resize partition #%zu."), partno + 1);
	fdisk_unref_table(tb);
	return -ERANGE;

}
Exemple #5
0
void list_freespace(struct fdisk_context *cxt)
{
	struct fdisk_table *tb = NULL;
	struct fdisk_partition *pa = NULL;
	struct fdisk_iter *itr = NULL;
	struct libscols_table *out = NULL;
	const char *bold = NULL;
	size_t i;
	uintmax_t sumsize = 0, bytes = 0;
	char *strsz;

	static const char *colnames[] = { N_("Start"), N_("End"), N_("Sectors"), N_("Size") };
	static const int colids[] = { FDISK_FIELD_START, FDISK_FIELD_END, FDISK_FIELD_SECTORS, FDISK_FIELD_SIZE };

	if (fdisk_get_freespaces(cxt, &tb))
		goto done;

	itr = fdisk_new_iter(FDISK_ITER_FORWARD);
	if (!itr) {
		fdisk_warn(cxt, _("failed to allocate iterator"));
		goto done;
	}

	out = scols_new_table();
	if (!out) {
		fdisk_warn(cxt, _("failed to allocate output table"));
		goto done;
	}

	if (colors_wanted()) {
		scols_table_enable_colors(out, 1);
		bold = color_scheme_get_sequence("header", UL_COLOR_BOLD);
	}

	for (i = 0; i < ARRAY_SIZE(colnames); i++) {
		struct libscols_column *co = scols_table_new_column(out, _(colnames[i]), 5, SCOLS_FL_RIGHT);

		if (!co)
			goto done;
		if (bold)
			scols_cell_set_color(scols_column_get_header(co), bold);
	}

	/* fill-in output table */
	while (fdisk_table_next_partition(tb, itr, &pa) == 0) {
		struct libscols_line *ln = scols_table_new_line(out, NULL);
		char *data;

		if (!ln) {
			fdisk_warn(cxt, _("failed to allocate output line"));
			goto done;
		}
		for (i = 0; i < ARRAY_SIZE(colids); i++) {
			if (fdisk_partition_to_string(pa, cxt, colids[i], &data))
				continue;
			scols_line_refer_data(ln, i, data);
		}

		if (fdisk_partition_has_size(pa))
			sumsize += fdisk_partition_get_size(pa);
	}

	bytes = sumsize * fdisk_get_sector_size(cxt);
	strsz = size_to_human_string(SIZE_SUFFIX_SPACE
					   | SIZE_SUFFIX_3LETTER, bytes);

	color_scheme_enable("header", UL_COLOR_BOLD);
	fdisk_info(cxt,	_("Unpartitioned space %s: %s, %ju bytes, %ju sectors"),
			fdisk_get_devname(cxt), strsz,
			bytes, sumsize);
	color_disable();
	free(strsz);

	fdisk_info(cxt, _("Units: %s of %d * %ld = %ld bytes"),
	       fdisk_get_unit(cxt, FDISK_PLURAL),
	       fdisk_get_units_per_sector(cxt),
	       fdisk_get_sector_size(cxt),
	       fdisk_get_units_per_sector(cxt) * fdisk_get_sector_size(cxt));

	fdisk_info(cxt, _("Sector size (logical/physical): %lu bytes / %lu bytes"),
				fdisk_get_sector_size(cxt),
				fdisk_get_physector_size(cxt));

	/* print */
	if (!scols_table_is_empty(out)) {
		fdisk_info(cxt, "");	/* line break */
		scols_print_table(out);
	}
done:
	scols_unref_table(out);
	fdisk_unref_table(tb);
	fdisk_free_iter(itr);
}