static int sgi_probe_label(struct fdisk_context *cxt) { struct fdisk_sgi_label *sgi; struct sgi_disklabel *sgilabel; assert(cxt); assert(cxt->label); assert(fdisk_is_disklabel(cxt, SGI)); assert(sizeof(struct sgi_disklabel) <= 512); /* map first sector to header */ sgi = (struct fdisk_sgi_label *) cxt->label; sgi->header = (struct sgi_disklabel *) cxt->firstsector; sgilabel = sgi->header; if (be32_to_cpu(sgilabel->magic) != SGI_LABEL_MAGIC) { sgi->header = NULL; return 0; } /* * test for correct checksum */ if (sgi_pt_checksum(sgilabel) != 0) fdisk_warnx(cxt, _("Detected sgi disklabel with wrong checksum.")); clear_freelist(cxt); cxt->label->nparts_max = SGI_MAXPARTITIONS; cxt->label->nparts_cur = count_used_partitions(cxt); return 1; }
static int sun_delete_partition(struct fdisk_context *cxt, size_t partnum) { struct sun_disklabel *sunlabel; struct sun_partition *part; struct sun_info *info; unsigned int nsec; assert(cxt); assert(cxt->label); assert(fdisk_is_label(cxt, SUN)); sunlabel = self_disklabel(cxt); part = &sunlabel->partitions[partnum]; info = &sunlabel->vtoc.infos[partnum]; if (partnum == 2 && be16_to_cpu(info->id) == SUN_TAG_WHOLEDISK && !part->start_cylinder && (nsec = be32_to_cpu(part->num_sectors)) == cxt->geom.heads * cxt->geom.sectors * cxt->geom.cylinders) fdisk_info(cxt, _("If you want to maintain SunOS/Solaris compatibility, " "consider leaving this " "partition as Whole disk (5), starting at 0, with %u " "sectors"), nsec); info->id = cpu_to_be16(SUN_TAG_UNASSIGNED); part->num_sectors = 0; cxt->label->nparts_cur = count_used_partitions(cxt); fdisk_label_set_changed(cxt->label, 1); return 0; }
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 = sgi_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; }
static int sun_probe_label(struct fdisk_context *cxt) { struct fdisk_sun_label *sun; struct sun_disklabel *sunlabel; unsigned short *ush; int csum; int need_fixing = 0; assert(cxt); assert(cxt->label); assert(fdisk_is_label(cxt, SUN)); /* map first sector to header */ sun = (struct fdisk_sun_label *) cxt->label; sun->header = (struct sun_disklabel *) cxt->firstsector; sunlabel = sun->header; if (be16_to_cpu(sunlabel->magic) != SUN_LABEL_MAGIC) { sun->header = NULL; return 0; /* failed */ } ush = ((unsigned short *) (sunlabel + 1)) - 1; for (csum = 0; ush >= (unsigned short *)sunlabel;) csum ^= *ush--; if (csum) { fdisk_warnx(cxt, _("Detected sun disklabel with wrong checksum. " "Probably you'll have to set all the values, " "e.g. heads, sectors, cylinders and partitions " "or force a fresh label (s command in main menu)")); return 1; } cxt->label->nparts_max = SUN_MAXPARTITIONS; cxt->geom.heads = be16_to_cpu(sunlabel->nhead); cxt->geom.cylinders = be16_to_cpu(sunlabel->ncyl); cxt->geom.sectors = be16_to_cpu(sunlabel->nsect); if (be32_to_cpu(sunlabel->vtoc.version) != SUN_VTOC_VERSION) { fdisk_warnx(cxt, _("Detected sun disklabel with wrong version [%d]."), be32_to_cpu(sunlabel->vtoc.version)); need_fixing = 1; } if (be32_to_cpu(sunlabel->vtoc.sanity) != SUN_VTOC_SANITY) { fdisk_warnx(cxt, _("Detected sun disklabel with wrong vtoc.sanity [0x%08x]."), be32_to_cpu(sunlabel->vtoc.sanity)); need_fixing = 1; } if (be16_to_cpu(sunlabel->vtoc.nparts) != SUN_MAXPARTITIONS) { fdisk_warnx(cxt, _("Detected sun disklabel with wrong vtoc.nparts [%u]."), be16_to_cpu(sunlabel->vtoc.nparts)); need_fixing = 1; } if (need_fixing) { fdisk_warnx(cxt, _("Warning: Wrong values need to be fixed up and " "will be corrected by w(rite)")); 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); ush = (unsigned short *)sunlabel; 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); return 1; }
static int sgi_create_disklabel(struct fdisk_context *cxt) { struct fdisk_sgi_label *sgi; struct sgi_disklabel *sgilabel; struct hd_geometry geometry; sector_t llsectors; int res; /* the result from the ioctl */ int sec_fac; /* the sector factor */ assert(cxt); assert(cxt->label); assert(fdisk_is_disklabel(cxt, SGI)); sec_fac = cxt->sector_size / 512; /* determine the sector factor */ res = blkdev_get_sectors(cxt->dev_fd, &llsectors); #ifdef HDIO_GETGEO /* TODO: it seems unnecessary, geometry is already set in the context */ if (ioctl(cxt->dev_fd, HDIO_GETGEO, &geometry) < 0) { fdisk_warn(cxt, _("HDIO_GETGEO ioctl failed on %s"), cxt->dev_path); return -1; } cxt->geom.heads = geometry.heads; cxt->geom.sectors = geometry.sectors; if (res == 0) { /* the get device size ioctl was successful */ sector_t llcyls; llcyls = llsectors / (cxt->geom.heads * cxt->geom.sectors * sec_fac); cxt->geom.cylinders = llcyls; if (cxt->geom.cylinders != llcyls) /* truncated? */ cxt->geom.cylinders = ~0; } else { /* otherwise print error and use truncated version */ cxt->geom.cylinders = geometry.cylinders; fdisk_warnx(cxt, _("Warning: 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); } #endif fdisk_zeroize_firstsector(cxt); sgi = (struct fdisk_sgi_label *) cxt->label; sgi->header = (struct sgi_disklabel *) cxt->firstsector; sgilabel = sgi->header; sgilabel->magic = cpu_to_be32(SGI_LABEL_MAGIC); sgilabel->root_part_num = cpu_to_be16(0); sgilabel->swap_part_num = cpu_to_be16(1); /* sizeof(sgilabel->boot_file) = 16 > 6 */ memset(sgilabel->boot_file, 0, 16); strcpy((char *) sgilabel->boot_file, "/unix"); sgilabel->devparam.skew = (0); sgilabel->devparam.gap1 = (0); sgilabel->devparam.gap2 = (0); sgilabel->devparam.sparecyl = (0); sgilabel->devparam.pcylcount = cpu_to_be16(geometry.cylinders); sgilabel->devparam.head_vol0 = cpu_to_be16(0); sgilabel->devparam.ntrks = cpu_to_be16(geometry.heads); /* tracks/cylinder (heads) */ sgilabel->devparam.cmd_tag_queue_depth = (0); sgilabel->devparam.unused0 = (0); sgilabel->devparam.unused1 = cpu_to_be16(0); sgilabel->devparam.nsect = cpu_to_be16(geometry.sectors); /* sectors/track */ sgilabel->devparam.bytes = cpu_to_be16(cxt->sector_size); sgilabel->devparam.ilfact = cpu_to_be16(1); sgilabel->devparam.flags = cpu_to_be32( SGI_DEVPARAM_TRACK_FWD | SGI_DEVPARAM_IGNORE_ERRORS | SGI_DEVPARAM_RESEEK); sgilabel->devparam.datarate = cpu_to_be32(0); sgilabel->devparam.retries_on_error = cpu_to_be32(1); sgilabel->devparam.ms_per_word = cpu_to_be32(0); sgilabel->devparam.xylogics_gap1 = cpu_to_be16(0); sgilabel->devparam.xylogics_syncdelay = cpu_to_be16(0); sgilabel->devparam.xylogics_readdelay = cpu_to_be16(0); sgilabel->devparam.xylogics_gap2 = cpu_to_be16(0); sgilabel->devparam.xylogics_readgate = cpu_to_be16(0); sgilabel->devparam.xylogics_writecont = cpu_to_be16(0); memset(&(sgilabel->volume), 0, sizeof(struct sgi_volume) * SGI_MAXVOLUMES); memset(&(sgilabel->partitions), 0, sizeof(struct sgi_partition) * SGI_MAXPARTITIONS); cxt->label->nparts_max = SGI_MAXPARTITIONS; sgi_set_entire(cxt); sgi_set_volhdr(cxt); cxt->label->nparts_cur = count_used_partitions(cxt); fdisk_sinfo(cxt, FDISK_INFO_SUCCESS, _("Created a new SGI disklabel.")); 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_create_disklabel(struct fdisk_context *cxt) { struct hd_geometry geometry; sector_t llsectors, llcyls; unsigned int ndiv, sec_fac; int res; struct fdisk_sun_label *sun; /* libfdisk sun handler */ struct sun_disklabel *sunlabel; /* on disk data */ assert(cxt); assert(cxt->label); assert(fdisk_is_disklabel(cxt, SUN)); /* map first sector to header */ fdisk_zeroize_firstsector(cxt); 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); res = blkdev_get_sectors(cxt->dev_fd, &llsectors); sec_fac = cxt->sector_size / 512; #ifdef HDIO_GETGEO if (!ioctl(cxt->dev_fd, HDIO_GETGEO, &geometry)) { cxt->geom.heads = geometry.heads; cxt->geom.sectors = geometry.sectors; if (res == 0) { llcyls = llsectors / (cxt->geom.heads * cxt->geom.sectors * sec_fac); cxt->geom.cylinders = llcyls; if (cxt->geom.cylinders != llcyls) cxt->geom.cylinders = ~0; } else { cxt->geom.cylinders = geometry.cylinders; 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 %llu alt %u hd %u sec %llu", cxt->geom.cylinders, be16_to_cpu(sunlabel->acyl), cxt->geom.heads, 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; set_sun_partition(cxt, 0, 0, ndiv * cxt->geom.heads * cxt->geom.sectors, SUN_TAG_LINUX_NATIVE); set_sun_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_sun_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_sinfo(cxt, FDISK_INFO_SUCCESS, _("Created a new Sun disklabel.")); return 0; }
static int sgi_create_disklabel(struct fdisk_context *cxt) { struct fdisk_sgi_label *sgi; struct sgi_disklabel *sgilabel; int rc; assert(cxt); assert(cxt->label); assert(fdisk_is_label(cxt, SGI)); #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) { /* the get device size ioctl was successful */ fdisk_sector_t llcyls; int sec_fac = cxt->sector_size / 512; llcyls = llsectors / (cxt->geom.heads * cxt->geom.sectors * sec_fac); cxt->geom.cylinders = llcyls; if (cxt->geom.cylinders != llcyls) /* truncated? */ cxt->geom.cylinders = ~0; } else { /* otherwise print error and use truncated version */ 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); } } #endif rc = fdisk_init_firstsector_buffer(cxt, 0, 0); if (rc) return rc; sgi = (struct fdisk_sgi_label *) cxt->label; sgi->header = (struct sgi_disklabel *) cxt->firstsector; sgilabel = sgi->header; sgilabel->magic = cpu_to_be32(SGI_LABEL_MAGIC); sgilabel->root_part_num = cpu_to_be16(0); sgilabel->swap_part_num = cpu_to_be16(1); /* sizeof(sgilabel->boot_file) = 16 > 6 */ memset(sgilabel->boot_file, 0, 16); strcpy((char *) sgilabel->boot_file, "/unix"); sgilabel->devparam.skew = (0); sgilabel->devparam.gap1 = (0); sgilabel->devparam.gap2 = (0); sgilabel->devparam.sparecyl = (0); sgilabel->devparam.pcylcount = cpu_to_be16(cxt->geom.cylinders); sgilabel->devparam.head_vol0 = cpu_to_be16(0); sgilabel->devparam.ntrks = cpu_to_be16(cxt->geom.heads); /* tracks/cylinder (heads) */ sgilabel->devparam.cmd_tag_queue_depth = (0); sgilabel->devparam.unused0 = (0); sgilabel->devparam.unused1 = cpu_to_be16(0); sgilabel->devparam.nsect = cpu_to_be16(cxt->geom.sectors); /* sectors/track */ sgilabel->devparam.bytes = cpu_to_be16(cxt->sector_size); sgilabel->devparam.ilfact = cpu_to_be16(1); sgilabel->devparam.flags = cpu_to_be32( SGI_DEVPARAM_TRACK_FWD | SGI_DEVPARAM_IGNORE_ERRORS | SGI_DEVPARAM_RESEEK); sgilabel->devparam.datarate = cpu_to_be32(0); sgilabel->devparam.retries_on_error = cpu_to_be32(1); sgilabel->devparam.ms_per_word = cpu_to_be32(0); sgilabel->devparam.xylogics_gap1 = cpu_to_be16(0); sgilabel->devparam.xylogics_syncdelay = cpu_to_be16(0); sgilabel->devparam.xylogics_readdelay = cpu_to_be16(0); sgilabel->devparam.xylogics_gap2 = cpu_to_be16(0); sgilabel->devparam.xylogics_readgate = cpu_to_be16(0); sgilabel->devparam.xylogics_writecont = cpu_to_be16(0); memset(&(sgilabel->volume), 0, sizeof(struct sgi_volume) * SGI_MAXVOLUMES); memset(&(sgilabel->partitions), 0, sizeof(struct sgi_partition) * SGI_MAXPARTITIONS); cxt->label->nparts_max = SGI_MAXPARTITIONS; /* don't create default layout when a script defined */ if (!cxt->script) { sgi_set_entire(cxt); sgi_set_volhdr(cxt); } cxt->label->nparts_cur = count_used_partitions(cxt); fdisk_info(cxt, _("Created a new SGI disklabel.")); return 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; }