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); }
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); }
/* 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; }
/** * 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; }
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; }
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; }
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; }
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; }