Ejemplo n.º 1
0
/**
 * fdisk_get_unit:
 * @cxt: context
 * @n: FDISK_PLURAL or FDISK_SINGULAR
 *
 * Returns: unit name.
 */
const char *fdisk_get_unit(struct fdisk_context *cxt, int n)
{
	assert(cxt);

	if (fdisk_use_cylinders(cxt))
		return P_("cylinder", "cylinders", n);
	return P_("sector", "sectors", n);
}
Ejemplo n.º 2
0
/**
 * fdisk_get_units_per_sector:
 * @cxt: context
 *
 * This is necessary only for brain dead situations when we use "cylinders";
 *
 * Returns: number of "units" per sector, default is 1 if display unit is sector.
 */
unsigned int fdisk_get_units_per_sector(struct fdisk_context *cxt)
{
	assert(cxt);

	if (fdisk_use_cylinders(cxt)) {
		assert(cxt->geom.heads);
		return cxt->geom.heads * cxt->geom.sectors;
	}
	return 1;
}
Ejemplo n.º 3
0
/**
 * fdisk_label_get_fields_ids
 * @lb: label (or NULL for the current label)
 * @ids: returns allocated array with FDISK_FIELD_* IDs
 * @nids: returns number of items in fields
 *
 * This function returns the default fields for the label.
 *
 * Note that the set of the default fields depends on fdisk_enable_details()
 * function. If the details are enabled then this function usually returns more
 * fields.
 *
 * Returns 0 on success, otherwise, a corresponding error.
 */
int fdisk_label_get_fields_ids(
		struct fdisk_label *lb,
		struct fdisk_context *cxt,
		int **ids, size_t *nids)
{
	size_t i, n;
	int *c;

	assert(cxt);

	if (!lb)
		lb = cxt->label;
	if (!lb)
		return -EINVAL;
	if (!lb->fields || !lb->nfields)
		return -ENOSYS;
	c = calloc(lb->nfields, sizeof(int));
	if (!c)
		return -ENOMEM;
	for (n = 0, i = 0; i < lb->nfields; i++) {
		int id = lb->fields[i].id;

		if ((fdisk_is_details(cxt) &&
				(lb->fields[i].flags & FDISK_FIELDFL_EYECANDY))
		     || (!fdisk_is_details(cxt) &&
				(lb->fields[i].flags & FDISK_FIELDFL_DETAIL))
		     || (id == FDISK_FIELD_SECTORS &&
			         fdisk_use_cylinders(cxt))
		     || (id == FDISK_FIELD_CYLINDERS &&
			         !fdisk_use_cylinders(cxt)))
			continue;

		c[n++] = id;
	}
	if (ids)
		*ids = c;
	else
		free(c);
	if (nids)
		*nids = n;
	return 0;
}
Ejemplo n.º 4
0
void list_disk_geometry(struct fdisk_context *cxt)
{
	char *id = NULL;
	struct fdisk_label *lb = fdisk_get_label(cxt, NULL);
	uint64_t bytes = fdisk_get_nsectors(cxt) * fdisk_get_sector_size(cxt);
	char *strsz = size_to_human_string(SIZE_SUFFIX_SPACE
					   | SIZE_SUFFIX_3LETTER, bytes);

	color_scheme_enable("header", UL_COLOR_BOLD);
	fdisk_info(cxt,	_("Disk %s: %s, %ju bytes, %ju sectors"),
			fdisk_get_devname(cxt), strsz,
			bytes, (uintmax_t) fdisk_get_nsectors(cxt));
	color_disable();
	free(strsz);

	if (lb && (fdisk_label_require_geometry(lb) || fdisk_use_cylinders(cxt)))
		fdisk_info(cxt, _("Geometry: %d heads, %llu sectors/track, %llu cylinders"),
			       fdisk_get_geom_heads(cxt),
			       fdisk_get_geom_sectors(cxt),
			       fdisk_get_geom_cylinders(cxt));

	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));
	fdisk_info(cxt, _("I/O size (minimum/optimal): %lu bytes / %lu bytes"),
				fdisk_get_minimal_iosize(cxt),
				fdisk_get_optimal_iosize(cxt));
	if (fdisk_get_alignment_offset(cxt))
		fdisk_info(cxt, _("Alignment offset: %lu bytes"),
				fdisk_get_alignment_offset(cxt));
	if (fdisk_has_label(cxt))
		fdisk_info(cxt, _("Disklabel type: %s"),
				fdisk_label_get_name(lb));

	if (fdisk_get_disklabel_id(cxt, &id) == 0 && id)
		fdisk_info(cxt, _("Disk identifier: %s"), id);
}
Ejemplo n.º 5
0
static int sun_add_partition(
		struct fdisk_context *cxt,
		struct fdisk_partition *pa,
		size_t *partno)
{
	struct sun_disklabel *sunlabel = self_disklabel(cxt);
	uint32_t starts[SUN_MAXPARTITIONS], lens[SUN_MAXPARTITIONS];
	struct sun_partition *part;
	struct sun_info *info;
	uint32_t start, stop, stop2;
	int whole_disk = 0;
	int sys = pa && pa->type ? pa->type->code : SUN_TAG_LINUX_NATIVE;
	int rc;
	size_t n;

	char mesg[256];
	size_t i;
	unsigned int first, last;

	rc = fdisk_partition_next_partno(pa, cxt, &n);
	if (rc)
		return rc;

	part = &sunlabel->partitions[n];
	info = &sunlabel->vtoc.infos[n];

	if (part->num_sectors && be16_to_cpu(info->id) != SUN_TAG_UNASSIGNED) {
		fdisk_info(cxt, _("Partition %zu is already defined.  Delete "
			"it before re-adding it."), n + 1);
		return -EINVAL;
	}

	fetch_sun(cxt, starts, lens, &start, &stop);

	if (stop <= start) {
		if (n == 2)
			whole_disk = 1;
		else {
			fdisk_info(cxt, _("Other partitions already cover the "
				"whole disk. Delete some/shrink them before retry."));
			return -EINVAL;
		}
	}

	if (pa && pa->start_follow_default)
		first = start;
	else if (pa && fdisk_partition_has_start(pa)) {
		first = pa->start;

		if (!whole_disk && !is_free_sector(cxt, first, starts, lens))
			return -ERANGE;
	} else {
		struct fdisk_ask *ask;

		snprintf(mesg, sizeof(mesg), _("First %s"),
				fdisk_get_unit(cxt, FDISK_SINGULAR));
		for (;;) {
			ask = fdisk_new_ask();
			if (!ask)
				return -ENOMEM;

			fdisk_ask_set_query(ask, mesg);
			fdisk_ask_set_type(ask, FDISK_ASKTYPE_NUMBER);

			if (whole_disk) {
				fdisk_ask_number_set_low(ask,     0);	/* minimal */
				fdisk_ask_number_set_default(ask, 0);	/* default */
				fdisk_ask_number_set_high(ask,    0);	/* maximal */
			} else {
				fdisk_ask_number_set_low(ask,     fdisk_scround(cxt, start));	/* minimal */
				fdisk_ask_number_set_default(ask, fdisk_scround(cxt, start));	/* default */
				fdisk_ask_number_set_high(ask,    fdisk_scround(cxt, stop));	/* maximal */
			}
			rc = fdisk_do_ask(cxt, ask);
			first = fdisk_ask_number_get_result(ask);
			fdisk_unref_ask(ask);
			if (rc)
				return rc;

			if (fdisk_use_cylinders(cxt))
				first *= fdisk_get_units_per_sector(cxt);

			/* ewt asks to add: "don't start a partition at cyl 0"
			   However, [email protected] writes:
			   "In addition to having a Sun partition table, to be able to
			   boot from the disc, the first partition, /dev/sdX1, must
			   start at cylinder 0. This means that /dev/sdX1 contains
			   the partition table and the boot block, as these are the
			   first two sectors of the disc. Therefore you must be
			   careful what you use /dev/sdX1 for. In particular, you must
			   not use a partition starting at cylinder 0 for Linux swap,
			   as that would overwrite the partition table and the boot
			   block. You may, however, use such a partition for a UFS
			   or EXT2 file system, as these file systems leave the first
			   1024 bytes undisturbed. */
			/* On the other hand, one should not use partitions
			   starting at block 0 in an md, or the label will
			   be trashed. */
			if (!is_free_sector(cxt, first, starts,  lens) && !whole_disk) {
				if (n == 2 && !first) {
				    whole_disk = 1;
				    break;
				}
				fdisk_warnx(cxt, _("Sector %d is already allocated"), first);
			} else
				break;
		}
	}

	if (n == 2 && first != 0)
		fdisk_warnx(cxt, _("It is highly recommended that the "
				   "third partition covers the whole disk "
				   "and is of type `Whole disk'"));

	if (!fdisk_use_cylinders(cxt)) {
		/* Starting sector has to be properly aligned */
		int cs = cxt->geom.heads * cxt->geom.sectors;
		int x = first % cs;

		if (x) {
			fdisk_info(cxt, _("Aligning the first sector from %u to %u "
					  "to be on cylinder boundary."),
					first, first + cs - x);
			first += cs - x;
		}
	}

	stop = cxt->geom.cylinders * cxt->geom.heads * cxt->geom.sectors;	/* ancient */
	stop2 = stop;
	for (i = 0; i < cxt->label->nparts_max; i++) {
		if (starts[i] > first && starts[i] < stop)
			stop = starts[i];
	}

	/* last */
	if (pa && pa->end_follow_default)
		last = whole_disk || (n == 2 && !first) ? stop2 : stop;
	else if (pa && fdisk_partition_has_size(pa)) {
		last = first + pa->size - 1ULL;

		if (!whole_disk && last > stop)
			return -ERANGE;
	} else {
		struct fdisk_ask *ask = fdisk_new_ask();

		if (!ask)
			return -ENOMEM;

		snprintf(mesg, sizeof(mesg),
			 _("Last %s or +%s or +size{K,M,G,T,P}"),
			 fdisk_get_unit(cxt, FDISK_SINGULAR),
			 fdisk_get_unit(cxt, FDISK_PLURAL));
		fdisk_ask_set_query(ask, mesg);
		fdisk_ask_set_type(ask, FDISK_ASKTYPE_OFFSET);

		if (whole_disk) {
			fdisk_ask_number_set_low(ask,     fdisk_scround(cxt, stop2));	/* minimal */
			fdisk_ask_number_set_default(ask, fdisk_scround(cxt, stop2));	/* default */
			fdisk_ask_number_set_high(ask,    fdisk_scround(cxt, stop2));	/* maximal */
			fdisk_ask_number_set_base(ask,    0);
		} else if (n == 2 && !first) {
			fdisk_ask_number_set_low(ask,     fdisk_scround(cxt, first));	/* minimal */
			fdisk_ask_number_set_default(ask, fdisk_scround(cxt, stop2));	/* default */
			fdisk_ask_number_set_high(ask,    fdisk_scround(cxt, stop2));	/* maximal */
			fdisk_ask_number_set_base(ask,	  fdisk_scround(cxt, first));
		} else {
			fdisk_ask_number_set_low(ask,     fdisk_scround(cxt, first));	/* minimal */
			fdisk_ask_number_set_default(ask, fdisk_scround(cxt, stop));	/* default */
			fdisk_ask_number_set_high(ask,    fdisk_scround(cxt, stop));	/* maximal */
			fdisk_ask_number_set_base(ask,    fdisk_scround(cxt, first));
		}

		if (fdisk_use_cylinders(cxt))
			fdisk_ask_number_set_unit(ask,
				     cxt->sector_size *
				     fdisk_get_units_per_sector(cxt));
		else
			fdisk_ask_number_set_unit(ask,	cxt->sector_size);

		rc = fdisk_do_ask(cxt, ask);
		last = fdisk_ask_number_get_result(ask);

		fdisk_unref_ask(ask);
		if (rc)
			return rc;
		if (fdisk_use_cylinders(cxt))
			last *= fdisk_get_units_per_sector(cxt);
	}

	if (n == 2 && !first) {
		if (last >= stop2) {
		    whole_disk = 1;
		    last = stop2;
		} else if (last > stop) {
		    fdisk_warnx(cxt,
   _("You haven't covered the whole disk with the 3rd partition, but your value\n"
     "%lu %s covers some other partition. Your entry has been changed\n"
     "to %lu %s"),
			(unsigned long) fdisk_scround(cxt, last), fdisk_get_unit(cxt, FDISK_SINGULAR),
			(unsigned long) fdisk_scround(cxt, stop), fdisk_get_unit(cxt, FDISK_SINGULAR));
		    last = stop;
		}
	} else if (!whole_disk && last > stop)
		last = stop;

	if (whole_disk)
		sys = SUN_TAG_WHOLEDISK;

	set_partition(cxt, n, first, last, sys);
	cxt->label->nparts_cur = count_used_partitions(cxt);
	if (partno)
		*partno = n;
	return 0;
}
Ejemplo n.º 6
0
static int sgi_add_partition(struct fdisk_context *cxt,
			     struct fdisk_partition *pa,
			     size_t *partno)
{
	struct fdisk_sgi_label *sgi;
	char mesg[256];
	unsigned int first = 0, last = 0;
	struct fdisk_ask *ask;
	int sys = pa && pa->type ? pa->type->code : SGI_TYPE_XFS;
	int rc;
	size_t n;

	assert(cxt);
	assert(cxt->label);
	assert(fdisk_is_label(cxt, SGI));

	rc = fdisk_partition_next_partno(pa, cxt, &n);
	if (rc)
		return rc;
	if (n == 10)
		sys = SGI_TYPE_ENTIRE_DISK;
	else if (n == 8)
		sys = 0;

	sgi = self_label(cxt);

	if (sgi_get_num_sectors(cxt, n)) {
		fdisk_warnx(cxt, _("Partition %zu is already defined.  "
				   "Delete it before re-adding it."), n + 1);
		return -EINVAL;
	}
	if (!cxt->script && sgi_entire(cxt) == -1 &&  sys != SGI_TYPE_ENTIRE_DISK) {
		fdisk_info(cxt, _("Attempting to generate entire disk entry automatically."));
		sgi_set_entire(cxt);
		sgi_set_volhdr(cxt);
	}
	if (sgi_gaps(cxt) == 0 && sys != SGI_TYPE_ENTIRE_DISK) {
		fdisk_warnx(cxt, _("The entire disk is already covered with partitions."));
		return -EINVAL;
	}
	if (sgi_gaps(cxt) < 0) {
		fdisk_warnx(cxt, _("You got a partition overlap on the disk. Fix it first!"));
		return -EINVAL;
	}

	if (sys == SGI_TYPE_ENTIRE_DISK) {
		first = 0;
		last = sgi_get_lastblock(cxt);
	} else {
		first = sgi->freelist[0].first;
		last  = sgi->freelist[0].last;
	}

	/* first sector */
	if (pa && pa->start_follow_default)
		;
	else if (pa && fdisk_partition_has_start(pa)) {
		first = pa->start;
		last = is_in_freelist(cxt, first);

		if (sys != SGI_TYPE_ENTIRE_DISK && !last)
			return -ERANGE;
	} else {
		snprintf(mesg, sizeof(mesg), _("First %s"),
				fdisk_get_unit(cxt, FDISK_SINGULAR));
		ask = fdisk_new_ask();
		if (!ask)
			return -ENOMEM;

		fdisk_ask_set_query(ask, mesg);
		fdisk_ask_set_type(ask, FDISK_ASKTYPE_NUMBER);

		fdisk_ask_number_set_low(ask,     fdisk_scround(cxt, first));	/* minimal */
		fdisk_ask_number_set_default(ask, fdisk_scround(cxt, first));	/* default */
		fdisk_ask_number_set_high(ask,    fdisk_scround(cxt, last) - 1); /* maximal */

		rc = fdisk_do_ask(cxt, ask);
		first = fdisk_ask_number_get_result(ask);
		fdisk_unref_ask(ask);

		if (rc)
			return rc;
		if (fdisk_use_cylinders(cxt))
			first *= fdisk_get_units_per_sector(cxt);
	}

	if (first && sys == SGI_TYPE_ENTIRE_DISK)
		fdisk_info(cxt, _("It is highly recommended that the "
				  "eleventh partition covers the entire "
				  "disk and is of type 'SGI volume'."));
	if (!last)
		last = is_in_freelist(cxt, first);

	/* last sector */
	if (pa && pa->end_follow_default)
		last -= 1ULL;
	else if (pa && fdisk_partition_has_size(pa)) {
		if (first + pa->size - 1ULL > last)
			return -ERANGE;
		last = first + pa->size - 1ULL;
	} else {
		snprintf(mesg, sizeof(mesg),
			 _("Last %s or +%s or +size{K,M,G,T,P}"),
			 fdisk_get_unit(cxt, FDISK_SINGULAR),
			 fdisk_get_unit(cxt, FDISK_PLURAL));

		ask = fdisk_new_ask();
		if (!ask)
			return -ENOMEM;

		fdisk_ask_set_query(ask, mesg);
		fdisk_ask_set_type(ask, FDISK_ASKTYPE_OFFSET);

		fdisk_ask_number_set_low(ask,     fdisk_scround(cxt, first));	/* minimal */
		fdisk_ask_number_set_default(ask, fdisk_scround(cxt, last) - 1);/* default */
		fdisk_ask_number_set_high(ask,    fdisk_scround(cxt, last) - 1);/* maximal */
		fdisk_ask_number_set_base(ask,    fdisk_scround(cxt, first));

		if (fdisk_use_cylinders(cxt))
			fdisk_ask_number_set_unit(ask,
				     cxt->sector_size *
				     fdisk_get_units_per_sector(cxt));
		else
			fdisk_ask_number_set_unit(ask,cxt->sector_size);

		rc = fdisk_do_ask(cxt, ask);
		last = fdisk_ask_number_get_result(ask) + 1;

		fdisk_unref_ask(ask);
		if (rc)
			return rc;
		if (fdisk_use_cylinders(cxt))
			last *= fdisk_get_units_per_sector(cxt);
	}

	if (sys == SGI_TYPE_ENTIRE_DISK
	    && (first != 0 || last != sgi_get_lastblock(cxt)))
		fdisk_info(cxt, _("It is highly recommended that the "
				  "eleventh partition covers the entire "
				  "disk and is of type 'SGI volume'."));

	set_partition(cxt, n, first, last - first, sys);
	cxt->label->nparts_cur = count_used_partitions(cxt);
	if (partno)
		*partno = n;
	return 0;
}