static int bsd_write_disklabel(struct fdisk_context *cxt) { off_t offset = 0; struct fdisk_bsd_label *l = self_label(cxt); struct bsd_disklabel *d = self_disklabel(cxt); if (l->dos_part) offset = dos_partition_get_start(l->dos_part) * cxt->sector_size; d->d_checksum = 0; d->d_checksum = bsd_dkcksum(d); /* Update label within boot block. */ memmove(&l->bsdbuffer[BSD_LABELSECTOR * DEFAULT_SECTOR_SIZE + BSD_LABELOFFSET], d, sizeof(*d)); #if defined (__alpha__) && BSD_LABELSECTOR == 0 /* Write the checksum to the end of the first sector. */ alpha_bootblock_checksum(l->bsdbuffer); #endif if (lseek(cxt->dev_fd, offset, SEEK_SET) == -1) { fdisk_warn(cxt, _("seek on %s failed"), cxt->dev_path); return -errno; } if (write_all(cxt->dev_fd, l->bsdbuffer, sizeof(l->bsdbuffer))) { fdisk_warn(cxt, _("cannot write %s"), cxt->dev_path); return -errno; } sync_disks(cxt); fdisk_sinfo(cxt, FDISK_INFO_SUCCESS, _("Disklabel written to %s."), cxt->dev_path); return 0; }
int fdisk_sgi_set_bootfile(struct fdisk_context *cxt) { int rc = 0; size_t sz; char *name = NULL; struct sgi_disklabel *sgilabel = self_disklabel(cxt); fdisk_info(cxt, _("The current boot file is: %s"), sgilabel->boot_file); rc = fdisk_ask_string(cxt, _("Enter of the new boot file"), &name); if (rc == 0) rc = sgi_check_bootfile(cxt, name); if (rc) { if (rc == 1) fdisk_info(cxt, _("Boot file unchanged")); goto done; } memset(sgilabel->boot_file, 0, sizeof(sgilabel->boot_file)); sz = strlen(name); assert(sz <= sizeof(sgilabel->boot_file)); /* see sgi_check_bootfile() */ memcpy(sgilabel->boot_file, name, sz); fdisk_sinfo(cxt, FDISK_INFO_SUCCESS, _("Bootfile is changed to \"%s\"."), name); done: free(name); return rc; }
void change_partition_type(struct fdisk_context *cxt) { size_t i; struct fdisk_parttype *t = NULL, *org_t = NULL; assert(cxt); assert(cxt->label); if (fdisk_ask_partnum(cxt, &i, FALSE)) return; org_t = t = fdisk_get_partition_type(cxt, i); if (!t) fdisk_warnx(cxt, _("Partition %zu does not exist yet!"), i + 1); else { do { t = ask_partition_type(cxt); } while (!t); if (fdisk_set_partition_type(cxt, i, t) == 0) fdisk_sinfo(cxt, FDISK_INFO_SUCCESS, _("Changed type of partition '%s' to '%s'."), org_t ? org_t->name : _("Unknown"), t ? t->name : _("Unknown")); else fdisk_info(cxt, _("Type of partition %zu is unchanged: %s."), i + 1, org_t ? org_t->name : _("Unknown")); } fdisk_free_parttype(t); fdisk_free_parttype(org_t); }
int fdisk_info_new_partition( struct fdisk_context *cxt, int num, sector_t start, sector_t stop, struct fdisk_parttype *t) { int rc; char *str = size_to_human_string(SIZE_SUFFIX_3LETTER | SIZE_SUFFIX_SPACE, (uint64_t)(stop - start + 1) * cxt->sector_size); rc = fdisk_sinfo(cxt, FDISK_INFO_SUCCESS, _("Created a new partition %d of type '%s' and of size %s."), num, t ? t->name : _("Unknown"), str); free(str); return rc; }
/* * link partition from parent (DOS) to nested BSD partition table */ int fdisk_bsd_link_partition(struct fdisk_context *cxt) { size_t k, i; int rc; struct dos_partition *p; struct bsd_disklabel *d = self_disklabel(cxt); if (!cxt->parent || !fdisk_is_disklabel(cxt->parent, DOS)) { fdisk_warnx(cxt, _("BSD label is not nested within a DOS partition.")); return -EINVAL; } /* ask for DOS partition */ rc = fdisk_ask_partnum(cxt->parent, &k, FALSE); if (rc) return rc; /* ask for BSD partition */ rc = fdisk_ask_partnum(cxt, &i, TRUE); if (rc) return rc; if (i >= BSD_MAXPARTITIONS) return -EINVAL; p = fdisk_dos_get_partition(cxt->parent, k); d->d_partitions[i].p_size = dos_partition_get_size(p); d->d_partitions[i].p_offset = dos_partition_get_start(p); d->d_partitions[i].p_fstype = bsd_translate_fstype(p->sys_ind); if (i >= d->d_npartitions) d->d_npartitions = i + 1; cxt->label->nparts_cur = d->d_npartitions; fdisk_label_set_changed(cxt->label, 1); fdisk_sinfo(cxt, FDISK_INFO_SUCCESS, _("BSD partition '%c' linked to DOS partition %zu."), 'a' + (int) i, k + 1); return 0; }
static int bsd_get_bootstrap(struct fdisk_context *cxt, char *path, void *ptr, int size) { int fd; if ((fd = open(path, O_RDONLY)) < 0) { fdisk_warn(cxt, _("cannot open %s"), path); return -errno; } if (read_all(fd, ptr, size) != size) { fdisk_warn(cxt, _("cannot read %s"), path); close(fd); return -errno; } fdisk_sinfo(cxt, FDISK_INFO_SUCCESS, _("The bootstrap file %s successfully loaded."), path); close (fd); return 0; }
int fdisk_bsd_write_bootstrap(struct fdisk_context *cxt) { struct bsd_disklabel dl, *d = self_disklabel(cxt); struct fdisk_bsd_label *l = self_label(cxt); char *name = d->d_type == BSD_DTYPE_SCSI ? "sd" : "wd"; char buf[BUFSIZ]; char *res, *dp, *p; int rc; sector_t sector; snprintf(buf, sizeof(buf), _("Bootstrap: %1$sboot -> boot%1$s (default %1$s)"), name); rc = fdisk_ask_string(cxt, buf, &res); if (rc) goto done; if (res && *res) name = res; snprintf(buf, sizeof(buf), "%s/%sboot", BSD_LINUX_BOOTDIR, name); rc = bsd_get_bootstrap(cxt, buf, l->bsdbuffer, (int) d->d_secsize); if (rc) goto done; /* We need a backup of the disklabel (might have changed). */ dp = &l->bsdbuffer[BSD_LABELSECTOR * DEFAULT_SECTOR_SIZE]; memmove(&dl, dp, sizeof(struct bsd_disklabel)); /* The disklabel will be overwritten by 0's from bootxx anyway */ memset(dp, 0, sizeof(struct bsd_disklabel)); snprintf(buf, sizeof(buf), "%s/boot%s", BSD_LINUX_BOOTDIR, name); rc = bsd_get_bootstrap(cxt, buf, &l->bsdbuffer[d->d_secsize], (int) d->d_bbsize - d->d_secsize); if (rc) goto done; /* check end of the bootstrap */ for (p = dp; p < dp + sizeof(struct bsd_disklabel); p++) { if (!*p) continue; fdisk_warnx(cxt, _("Bootstrap overlaps with disklabel!")); return -EINVAL; } /* move disklabel back */ memmove(dp, &dl, sizeof(struct bsd_disklabel)); sector = 0; if (l->dos_part) sector = dos_partition_get_start(l->dos_part); #if defined (__alpha__) alpha_bootblock_checksum(l->bsdbuffer); #endif if (lseek(cxt->dev_fd, (off_t) sector * DEFAULT_SECTOR_SIZE, SEEK_SET) == -1) { fdisk_warn(cxt, _("seek on %s failed"), cxt->dev_path); rc = -errno; goto done; } if (write_all(cxt->dev_fd, l->bsdbuffer, BSD_BBSIZE)) { fdisk_warn(cxt, _("cannot write %s"), cxt->dev_path); rc = -errno; goto done; } fdisk_sinfo(cxt, FDISK_INFO_SUCCESS, _("Bootstrap installed on %s."), cxt->dev_path); sync_disks(cxt); rc = 0; done: free(res); return rc; }
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 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 */ 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); #ifdef HDIO_GETGEO if (cxt->geom.heads && cxt->geom.sectors) { sector_t llsectors; if (blkdev_get_sectors(cxt->dev_fd, &llsectors) == 0) { int sec_fac = cxt->sector_size / 512; 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 %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; }