static void sgi_set_entire(struct fdisk_context *cxt) { size_t n; for (n = 10; n < cxt->label->nparts_max; n++) { if (!sgi_get_num_sectors(cxt, n)) { set_partition(cxt, n, 0, sgi_get_lastblock(cxt), SGI_TYPE_ENTIRE_DISK); break; } } }
static void sgi_set_volhdr(struct fdisk_context *cxt) { size_t n; for (n = 8; n < cxt->label->nparts_max; n++) { if (!sgi_get_num_sectors(cxt, n)) { /* Choose same default volume header size as IRIX fx uses. */ if (4096 < sgi_get_lastblock(cxt)) set_partition(cxt, n, 0, 4096, SGI_TYPE_VOLHDR); break; } } }
static int sgi_delete_partition(struct fdisk_context *cxt, size_t partnum) { int rc; assert(cxt); assert(cxt->label); if (partnum > cxt->label->nparts_max) return -EINVAL; rc = set_partition(cxt, partnum, 0, 0, 0); cxt->label->nparts_cur = count_used_partitions(cxt); return rc; }
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; }
static int sun_create_disklabel(struct fdisk_context *cxt) { unsigned int ndiv; struct fdisk_sun_label *sun; /* libfdisk sun handler */ struct sun_disklabel *sunlabel; /* on disk data */ int rc = 0; assert(cxt); assert(cxt->label); assert(fdisk_is_label(cxt, SUN)); /* map first sector to header */ rc = fdisk_init_firstsector_buffer(cxt, 0, 0); if (rc) return rc; sun = (struct fdisk_sun_label *) cxt->label; sun->header = (struct sun_disklabel *) cxt->firstsector; sunlabel = sun->header; cxt->label->nparts_max = SUN_MAXPARTITIONS; sunlabel->magic = cpu_to_be16(SUN_LABEL_MAGIC); sunlabel->vtoc.version = cpu_to_be32(SUN_VTOC_VERSION); sunlabel->vtoc.sanity = cpu_to_be32(SUN_VTOC_SANITY); sunlabel->vtoc.nparts = cpu_to_be16(SUN_MAXPARTITIONS); #ifdef HDIO_GETGEO if (cxt->geom.heads && cxt->geom.sectors) { fdisk_sector_t llsectors; if (blkdev_get_sectors(cxt->dev_fd, (unsigned long long *) &llsectors) == 0) { int sec_fac = cxt->sector_size / 512; fdisk_sector_t llcyls; llcyls = llsectors / (cxt->geom.heads * cxt->geom.sectors * sec_fac); cxt->geom.cylinders = llcyls; if (cxt->geom.cylinders != llcyls) cxt->geom.cylinders = ~0; } else { fdisk_warnx(cxt, _("BLKGETSIZE ioctl failed on %s. " "Using geometry cylinder value of %llu. " "This value may be truncated for devices " "> 33.8 GB."), cxt->dev_path, cxt->geom.cylinders); } } else #endif ask_geom(cxt); sunlabel->acyl = cpu_to_be16(0); sunlabel->pcyl = cpu_to_be16(cxt->geom.cylinders); sunlabel->rpm = cpu_to_be16(5400); sunlabel->intrlv = cpu_to_be16(1); sunlabel->apc = cpu_to_be16(0); sunlabel->nhead = cpu_to_be16(cxt->geom.heads); sunlabel->nsect = cpu_to_be16(cxt->geom.sectors); sunlabel->ncyl = cpu_to_be16(cxt->geom.cylinders); snprintf((char *) sunlabel->label_id, sizeof(sunlabel->label_id), "Linux cyl %ju alt %u hd %u sec %ju", (uintmax_t) cxt->geom.cylinders, be16_to_cpu(sunlabel->acyl), cxt->geom.heads, (uintmax_t) cxt->geom.sectors); if (cxt->geom.cylinders * cxt->geom.heads * cxt->geom.sectors >= 150 * 2048) { ndiv = cxt->geom.cylinders - (50 * 2048 / (cxt->geom.heads * cxt->geom.sectors)); /* 50M swap */ } else ndiv = cxt->geom.cylinders * 2 / 3; /* create the default layout only if no-script defined */ if (!cxt->script) { set_partition(cxt, 0, 0, ndiv * cxt->geom.heads * cxt->geom.sectors, SUN_TAG_LINUX_NATIVE); set_partition(cxt, 1, ndiv * cxt->geom.heads * cxt->geom.sectors, cxt->geom.cylinders * cxt->geom.heads * cxt->geom.sectors, SUN_TAG_LINUX_SWAP); sunlabel->vtoc.infos[1].flags |= cpu_to_be16(SUN_FLAG_UNMNT); set_partition(cxt, 2, 0, cxt->geom.cylinders * cxt->geom.heads * cxt->geom.sectors, SUN_TAG_WHOLEDISK); } { unsigned short *ush = (unsigned short *)sunlabel; unsigned short csum = 0; while(ush < (unsigned short *)(&sunlabel->csum)) csum ^= *ush++; sunlabel->csum = csum; } fdisk_label_set_changed(cxt->label, 1); cxt->label->nparts_cur = count_used_partitions(cxt); fdisk_info(cxt, _("Created a new Sun disklabel.")); return 0; }
void dos_add_partition(struct fdisk_context *cxt, int n, int sys) { char mesg[256]; /* 48 does not suffice in Japanese */ int i, read = 0; struct partition *p = ptes[n].part_table; struct partition *q = ptes[ext_index].part_table; sector_t start, stop = 0, limit, temp, first[partitions], last[partitions]; if (p && p->sys_ind) { printf(_("Partition %d is already defined. Delete " "it before re-adding it.\n"), n + 1); return; } fill_bounds(first, last); if (n < 4) { start = sector_offset; if (display_in_cyl_units || !cxt->total_sectors) limit = cxt->geom.heads * cxt->geom.sectors * cxt->geom.cylinders - 1; else limit = cxt->total_sectors - 1; if (limit > UINT_MAX) limit = UINT_MAX; if (extended_offset) { first[ext_index] = extended_offset; last[ext_index] = get_start_sect(q) + get_nr_sects(q) - 1; } } else { start = extended_offset + sector_offset; limit = get_start_sect(q) + get_nr_sects(q) - 1; } if (display_in_cyl_units) for (i = 0; i < partitions; i++) first[i] = (cround(first[i]) - 1) * units_per_sector; snprintf(mesg, sizeof(mesg), _("First %s"), str_units(SINGULAR)); do { sector_t dflt, aligned; temp = start; dflt = start = get_unused_start(n, start, first, last); /* the default sector should be aligned and unused */ do { aligned = align_lba_in_range(cxt, dflt, dflt, limit); dflt = get_unused_start(n, aligned, first, last); } while (dflt != aligned && dflt > aligned && dflt < limit); if (dflt >= limit) dflt = start; if (start > limit) break; if (start >= temp+units_per_sector && read) { printf(_("Sector %llu is already allocated\n"), temp); temp = start; read = 0; } if (!read && start == temp) { sector_t i = start; start = read_int(cxt, cround(i), cround(dflt), cround(limit), 0, mesg); if (display_in_cyl_units) { start = (start - 1) * units_per_sector; if (start < i) start = i; } read = 1; } } while (start != temp || !read); if (n > 4) { /* NOT for fifth partition */ struct pte *pe = &ptes[n]; pe->offset = start - sector_offset; if (pe->offset == extended_offset) { /* must be corrected */ pe->offset++; if (sector_offset == 1) start++; } } for (i = 0; i < partitions; i++) { struct pte *pe = &ptes[i]; if (start < pe->offset && limit >= pe->offset) limit = pe->offset - 1; if (start < first[i] && limit >= first[i]) limit = first[i] - 1; } if (start > limit) { printf(_("No free sectors available\n")); if (n > 4) partitions--; return; } if (cround(start) == cround(limit)) { stop = limit; } else { int is_suffix_used = 0; snprintf(mesg, sizeof(mesg), _("Last %1$s, +%2$s or +size{K,M,G}"), str_units(SINGULAR), str_units(PLURAL)); stop = read_int_with_suffix(cxt, cround(start), cround(limit), cround(limit), cround(start), mesg, &is_suffix_used); if (display_in_cyl_units) { stop = stop * units_per_sector - 1; if (stop >limit) stop = limit; } if (is_suffix_used && alignment_required) { /* the last sector has not been exactly requested (but * defined by +size{K,M,G} convention), so be smart * and align the end of the partition. The next * partition will start at phy.block boundary. */ stop = align_lba_in_range(cxt, stop, start, limit) - 1; if (stop > limit) stop = limit; } } set_partition(cxt, n, 0, start, stop, sys); if (n > 4) set_partition(cxt, n - 1, 1, ptes[n].offset, stop, EXTENDED); if (IS_EXTENDED (sys)) { struct pte *pe4 = &ptes[4]; struct pte *pen = &ptes[n]; ext_index = n; pen->ext_pointer = p; pe4->offset = extended_offset = start; pe4->sectorbuffer = xcalloc(1, cxt->sector_size); pe4->part_table = pt_offset(pe4->sectorbuffer, 0); pe4->ext_pointer = pe4->part_table + 1; pe4->changed = 1; partitions = 5; } }
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; }