Ejemplo n.º 1
0
void list_disk_geometry(struct fdisk_context *cxt)
{
	char *id = NULL;
	uint64_t bytes = cxt->total_sectors * cxt->sector_size;
	char *strsz = size_to_human_string(SIZE_SUFFIX_SPACE
					   | SIZE_SUFFIX_3LETTER, bytes);

	fdisk_colon(cxt,	_("Disk %s: %s, %ju bytes, %ju sectors"),
			cxt->dev_path, strsz,
			bytes, (uintmax_t) cxt->total_sectors);
	free(strsz);

	if (fdisk_require_geometry(cxt) || fdisk_context_use_cylinders(cxt))
		fdisk_colon(cxt, _("Geometry: %d heads, %llu sectors/track, %llu cylinders"),
			       cxt->geom.heads, cxt->geom.sectors, cxt->geom.cylinders);

	fdisk_colon(cxt, _("Units: %s of %d * %ld = %ld bytes"),
	       fdisk_context_get_unit(cxt, PLURAL),
	       fdisk_context_get_units_per_sector(cxt),
	       cxt->sector_size,
	       fdisk_context_get_units_per_sector(cxt) * cxt->sector_size);

	fdisk_colon(cxt, _("Sector size (logical/physical): %lu bytes / %lu bytes"),
				cxt->sector_size, cxt->phy_sector_size);
	fdisk_colon(cxt, _("I/O size (minimum/optimal): %lu bytes / %lu bytes"),
				cxt->min_io_size, cxt->io_size);
	if (cxt->alignment_offset)
		fdisk_colon(cxt, _("Alignment offset: %lu bytes"),
				cxt->alignment_offset);
	if (fdisk_dev_has_disklabel(cxt))
		fdisk_colon(cxt, _("Disklabel type: %s"), cxt->label->name);

	if (fdisk_get_disklabel_id(cxt, &id) == 0 && id)
		fdisk_colon(cxt, _("Disk identifier: %s"), id);
}
Ejemplo n.º 2
0
const char *fdisk_context_get_unit(struct fdisk_context *cxt, int n)
{
	assert(cxt);

	if (fdisk_context_use_cylinders(cxt))
		return P_("cylinder", "cylinders", n);
	return P_("sector", "sectors", n);
}
Ejemplo n.º 3
0
/* Returns number of "units" per sector, default is 1 if display unit is sector.
 */
unsigned int fdisk_context_get_units_per_sector(struct fdisk_context *cxt)
{
	assert(cxt);

	if (fdisk_context_use_cylinders(cxt)) {
		assert(cxt->geom.heads);
		return cxt->geom.heads * cxt->geom.sectors;
	}
	return 1;
}
Ejemplo n.º 4
0
/**
 * fdisk_get_columns:
 * @cxt: fdisk context
 * @all: 1 or 0
 * @cols: returns allocated array with FDISK_COL_* IDs
 * @ncols: returns number of items in cols
 *
 * This function returns the default or all columns for the current label.  The
 * library uses the columns for list operations (see fdisk_list_disklabel() and
 * fdisk_list_partitions()). Note that the set of the default columns depends
 * on fdisk_context_enable_details() function. If the details are eanable then
 * this function usually returns more columns.
 *
 * Returns 0 on success, otherwise, a corresponding error.
 */
int fdisk_get_columns(struct fdisk_context *cxt, int all, int **cols, size_t *ncols)
{
	size_t i, n;
	int *c;

	assert(cxt);

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

		if (!all &&
		    ((fdisk_context_display_details(cxt) &&
				(cxt->label->columns[i].flags & FDISK_COLFL_EYECANDY))
		     || (!fdisk_context_display_details(cxt) &&
				(cxt->label->columns[i].flags & FDISK_COLFL_DETAIL))
		     || (id == FDISK_COL_SECTORS &&
			         fdisk_context_use_cylinders(cxt))
		     || (id == FDISK_COL_CYLINDERS &&
			         !fdisk_context_use_cylinders(cxt))))
			continue;

		c[n++] = id;
	}
	if (cols)
		*cols = c;
	if (ncols)
		*ncols = n;
	return 0;
}
Ejemplo n.º 5
0
static int bsd_get_partition(struct fdisk_context *cxt, size_t n,
                             struct fdisk_partition *pa)
{
    struct bsd_partition *p;
    struct bsd_disklabel *d = self_disklabel(cxt);

    assert(cxt);
    assert(cxt->label);
    assert(fdisk_is_disklabel(cxt, BSD));

    if (n >= d->d_npartitions)
        return -EINVAL;

    p = &d->d_partitions[n];

    pa->used = p->p_size ? 1 : 0;
    if (!pa->used)
        return 0;

    if (fdisk_context_use_cylinders(cxt) && d->d_secpercyl) {
        pa->start_post = p->p_offset % d->d_secpercyl ? '*' : ' ';
        pa->end_post = (p->p_offset + p->p_size) % d->d_secpercyl ? '*' : ' ';
    }

    pa->start = p->p_offset;
    pa->end = p->p_offset + p->p_size - 1;
    pa->size = p->p_size;
    pa->type = bsd_partition_parttype(cxt, p);

    if (p->p_fstype == BSD_FS_UNUSED || p->p_fstype == BSD_FS_BSDFFS) {
        pa->fsize = p->p_fsize;
        pa->bsize = p->p_fsize * p->p_frag;
    }
    if (p->p_fstype == BSD_FS_BSDFFS)
        pa->cpg = p->p_cpg;

    return 0;
}
Ejemplo n.º 6
0
static int bsd_add_partition(struct fdisk_context *cxt,
                             struct fdisk_partition *pa)
{
    struct fdisk_bsd_label *l = self_label(cxt);
    struct bsd_disklabel *d = self_disklabel(cxt);
    size_t i;
    unsigned int begin = 0, end;
    int rc = 0;

    rc = fdisk_partition_next_partno(pa, cxt, &i);
    if (rc)
        return rc;
    if (i >= BSD_MAXPARTITIONS)
        return -ERANGE;
    if (l->dos_part) {
        begin = dos_partition_get_start(l->dos_part);
        end = begin + dos_partition_get_size(l->dos_part) - 1;
    } else
        end = d->d_secperunit - 1;

    /*
     * First sector
     */
    if (pa && pa->start_follow_default)
        ;
    else if (pa && pa->start) {
        if (pa->start < begin || pa->start > end)
            return -ERANGE;
        begin = pa->start;
    } else {
        struct fdisk_ask *ask = fdisk_new_ask();

        if (!ask)
            return -ENOMEM;
        fdisk_ask_set_query(ask,
                            fdisk_context_use_cylinders(cxt) ?
                            _("First cylinder") : _("First sector"));
        fdisk_ask_set_type(ask, FDISK_ASKTYPE_NUMBER);
        fdisk_ask_number_set_low(ask, fdisk_cround(cxt, begin));
        fdisk_ask_number_set_default(ask, fdisk_cround(cxt, begin));
        fdisk_ask_number_set_high(ask, fdisk_cround(cxt, end));

        rc = fdisk_do_ask(cxt, ask);
        begin = fdisk_ask_number_get_result(ask);
        fdisk_free_ask(ask);
        if (rc)
            return rc;
        if (fdisk_context_use_cylinders(cxt))
            begin = (begin - 1) * d->d_secpercyl;
    }

    /*
     * Last sector
     */
    if (pa && pa->end_follow_default)
        ;
    else if (pa && pa->size) {
        if (begin + pa->size > end)
            return -ERANGE;
        end = begin + pa->size;
    } else {
        /* ask user by dialog */
        struct fdisk_ask *ask = fdisk_new_ask();

        if (!ask)
            return -ENOMEM;
        fdisk_ask_set_type(ask, FDISK_ASKTYPE_OFFSET);

        if (fdisk_context_use_cylinders(cxt)) {
            fdisk_ask_set_query(ask, _("Last cylinder, +cylinders or +size{K,M,G,T,P}"));
            fdisk_ask_number_set_unit(ask,
                                      cxt->sector_size *
                                      fdisk_context_get_units_per_sector(cxt));
        } else {
            fdisk_ask_set_query(ask, _("Last sector, +sectors or +size{K,M,G,T,P}"));
            fdisk_ask_number_set_unit(ask,cxt->sector_size);
        }

        fdisk_ask_number_set_low(ask, fdisk_cround(cxt, begin));
        fdisk_ask_number_set_default(ask, fdisk_cround(cxt, end));
        fdisk_ask_number_set_high(ask, fdisk_cround(cxt, end));
        fdisk_ask_number_set_base(ask, fdisk_cround(cxt, begin));

        rc = fdisk_do_ask(cxt, ask);
        end = fdisk_ask_number_get_result(ask);
        fdisk_free_ask(ask);
        if (rc)
            return rc;
        if (fdisk_context_use_cylinders(cxt))
            end = end * d->d_secpercyl - 1;
    }

    d->d_partitions[i].p_size   = end - begin + 1;
    d->d_partitions[i].p_offset = begin;
    d->d_partitions[i].p_fstype = BSD_FS_UNUSED;

    if (i >= d->d_npartitions)
        d->d_npartitions = i + 1;
    cxt->label->nparts_cur = d->d_npartitions;

    if (pa && pa->type)
        bsd_set_parttype(cxt, i, pa->type);

    fdisk_label_set_changed(cxt->label, 1);
    return 0;
}
Ejemplo n.º 7
0
static int sgi_add_partition(struct fdisk_context *cxt,
		size_t n,
		struct fdisk_parttype *t)
{
	struct fdisk_sgi_label *sgi;
	char mesg[256];
	unsigned int first = 0, last = 0;
	struct fdisk_ask *ask;
	int sys = t ? t->type : SGI_TYPE_XFS;
	int rc;

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

	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 %zd is already defined.  Delete "
			 "it before re-adding it."), n + 1);
		return -EINVAL;
	}
	if (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;
	}

	snprintf(mesg, sizeof(mesg), _("First %s"),
			fdisk_context_get_unit(cxt, 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 (sys == SGI_TYPE_ENTIRE_DISK) {
			last = sgi_get_lastblock(cxt);
			fdisk_ask_number_set_low(ask,     0);	/* minimal */
			fdisk_ask_number_set_default(ask, 0);	/* default */
			fdisk_ask_number_set_high(ask, last - 1); /* maximal */
		} else {
			first = sgi->freelist[0].first;
			last  = sgi->freelist[0].last;
			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_free_ask(ask);

		if (rc)
			return rc;

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

		if (fdisk_context_use_cylinders(cxt))
			first *= fdisk_context_get_units_per_sector(cxt);
		/*else
			first = first; * align to cylinder if you know how ... */
		if (!last)
			last = is_in_freelist(cxt, first);
		if (last == 0)
			fdisk_warnx(cxt, _("You will get a partition overlap "
				"on the disk. Fix it first!"));
		else
			break;
	}

	snprintf(mesg, sizeof(mesg),
		 _("Last %s or +%s or +size{K,M,G,T,P}"),
		 fdisk_context_get_unit(cxt, SINGULAR),
		 fdisk_context_get_unit(cxt, 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_context_use_cylinders(cxt))
		fdisk_ask_number_set_unit(ask,
			     cxt->sector_size *
			     fdisk_context_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_free_ask(ask);
	if (rc)
		return rc;

	if (fdisk_context_use_cylinders(cxt))
		last *= fdisk_context_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 eleventh "
			"partition covers the entire disk and is of type "
			"`SGI volume'"));

	sgi_set_partition(cxt, n, first, last - first, sys);
	cxt->label->nparts_cur = count_used_partitions(cxt);

	return 0;
}
Ejemplo n.º 8
0
static int sun_add_partition(
		struct fdisk_context *cxt,
		size_t n,
		struct fdisk_parttype *t)
{
	struct sun_disklabel *sunlabel = self_disklabel(cxt);
	uint32_t starts[SUN_MAXPARTITIONS], lens[SUN_MAXPARTITIONS];
	struct sun_partition *part = &sunlabel->partitions[n];
	struct sun_info *info = &sunlabel->vtoc.infos[n];
	uint32_t start, stop, stop2;
	int whole_disk = 0, sys = t ? t->type : SUN_TAG_LINUX_NATIVE;
	struct fdisk_ask *ask;
	int rc;

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

	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;
		}
	}
	snprintf(mesg, sizeof(mesg), _("First %s"),
			fdisk_context_get_unit(cxt, 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_free_ask(ask);

		if (rc)
			return rc;

		if (fdisk_context_use_cylinders(cxt))
			first *= fdisk_context_get_units_per_sector(cxt);
		else {
			/* 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;
			}
		}
		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'"));
		/* 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. */
		for (i = 0; i < cxt->label->nparts_max; i++)
			if (lens[i] && starts[i] <= first
			            && starts[i] + lens[i] > first)
				break;
		if (i < cxt->label->nparts_max && !whole_disk) {
			if (n == 2 && !first) {
			    whole_disk = 1;
			    break;
			}
			fdisk_warnx(cxt, _("Sector %d is already allocated"), first);
		} else
			break;
	}
	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];
	}
	snprintf(mesg, sizeof(mesg),
		 _("Last %s or +%s or +size{K,M,G,T,P}"),
		 fdisk_context_get_unit(cxt, SINGULAR),
		 fdisk_context_get_unit(cxt, PLURAL));

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

	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_context_use_cylinders(cxt))
		fdisk_ask_number_set_unit(ask,
			     cxt->sector_size *
			     fdisk_context_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_free_ask(ask);
	if (rc)
		return rc;

	if (fdisk_context_use_cylinders(cxt))
		last *= fdisk_context_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_context_get_unit(cxt, SINGULAR),
			(unsigned long) fdisk_scround(cxt, stop), fdisk_context_get_unit(cxt, SINGULAR));
		    last = stop;
		}
	} else if (!whole_disk && last > stop)
		last = stop;

	if (whole_disk)
		sys = SUN_TAG_WHOLEDISK;

	set_sun_partition(cxt, n, first, last, sys);
	cxt->label->nparts_cur = count_used_partitions(cxt);
	return 0;
}