static int sun_write_disklabel(struct fdisk_context *cxt) { struct sun_disklabel *sunlabel; unsigned short *ush; unsigned short csum = 0; const size_t sz = sizeof(struct sun_disklabel); assert(cxt); assert(cxt->label); assert(fdisk_is_disklabel(cxt, SUN)); sunlabel = self_disklabel(cxt); /* Maybe geometry has been modified */ sunlabel->nhead = cpu_to_be16(cxt->geom.heads); sunlabel->nsect = cpu_to_be16(cxt->geom.sectors); if (cxt->geom.cylinders != be16_to_cpu(sunlabel->ncyl)) sunlabel->ncyl = cpu_to_be16( cxt->geom.cylinders - be16_to_cpu(sunlabel->acyl) ); ush = (unsigned short *) sunlabel; while(ush < (unsigned short *)(&sunlabel->csum)) csum ^= *ush++; sunlabel->csum = csum; if (lseek(cxt->dev_fd, 0, SEEK_SET) < 0) return -errno; if (write_all(cxt->dev_fd, sunlabel, sz) != 0) return -errno; return 0; }
static int sgi_toggle_partition_flag(struct fdisk_context *cxt, size_t i, unsigned long flag) { struct sgi_disklabel *sgilabel; assert(cxt); assert(cxt->label); assert(fdisk_is_disklabel(cxt, SGI)); if (i >= cxt->label->nparts_max) return -EINVAL; sgilabel = self_disklabel(cxt); switch (flag) { case SGI_FLAG_BOOT: sgilabel->root_part_num = be16_to_cpu(sgilabel->root_part_num) == i ? 0 : cpu_to_be16(i); fdisk_label_set_changed(cxt->label, 1); break; case SGI_FLAG_SWAP: sgilabel->swap_part_num = be16_to_cpu(sgilabel->swap_part_num) == i ? 0 : cpu_to_be16(i); fdisk_label_set_changed(cxt->label, 1); break; default: return 1; } return 0; }
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_disklabel(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_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 sgi_set_partition(struct fdisk_context *cxt, size_t i, unsigned int start, unsigned int length, int sys) { struct sgi_disklabel *sgilabel; assert(cxt); assert(cxt->label); assert(fdisk_is_disklabel(cxt, SGI)); sgilabel = self_disklabel(cxt); sgilabel->partitions[i].type = cpu_to_be32(sys); sgilabel->partitions[i].num_blocks = cpu_to_be32(length); sgilabel->partitions[i].first_block = cpu_to_be32(start); fdisk_label_set_changed(cxt->label, 1); if (sgi_gaps(cxt) < 0) /* rebuild freelist */ fdisk_warnx(cxt, _("Partition overlap on the disk.")); if (length) { struct fdisk_parttype *t = fdisk_get_parttype_from_code(cxt, sys); fdisk_info_new_partition(cxt, i + 1, start, start + length, t); } return 0; }
static int sun_toggle_partition_flag(struct fdisk_context *cxt, size_t i, unsigned long flag) { struct sun_disklabel *sunlabel; struct sun_info *p; assert(cxt); assert(cxt->label); assert(fdisk_is_disklabel(cxt, SUN)); if (i >= cxt->label->nparts_max) return -EINVAL; sunlabel = self_disklabel(cxt); p = &sunlabel->vtoc.infos[i]; switch (flag) { case SUN_FLAG_UNMNT: p->flags ^= cpu_to_be16(SUN_FLAG_UNMNT); fdisk_label_set_changed(cxt->label, 1); break; case SUN_FLAG_RONLY: p->flags ^= cpu_to_be16(SUN_FLAG_RONLY); fdisk_label_set_changed(cxt->label, 1); break; default: return 1; } return 0; }
/* return poiter buffer with on-disk data */ static inline struct sun_disklabel *self_disklabel(struct fdisk_context *cxt) { assert(cxt); assert(cxt->label); assert(fdisk_is_disklabel(cxt, SUN)); return ((struct fdisk_sun_label *) cxt->label)->header; }
/* return in-memory fdisk data */ static inline struct fdisk_sgi_label *self_label(struct fdisk_context *cxt) { assert(cxt); assert(cxt->label); assert(fdisk_is_disklabel(cxt, SGI)); return (struct fdisk_sgi_label *) cxt->label; }
static inline struct bsd_disklabel *self_disklabel(struct fdisk_context *cxt) { assert(cxt); assert(cxt->label); assert(fdisk_is_disklabel(cxt, BSD)); return &((struct fdisk_bsd_label *) cxt->label)->bsd; }
static int sgi_partition_is_used( struct fdisk_context *cxt, size_t i) { assert(cxt); assert(fdisk_is_disklabel(cxt, SGI)); if (i >= cxt->label->nparts_max) return 0; return sgi_get_num_sectors(cxt, i) ? 1 : 0; }
static int sun_set_parttype( struct fdisk_context *cxt, size_t i, struct fdisk_parttype *t) { struct sun_disklabel *sunlabel; struct sun_partition *part; struct sun_info *info; assert(cxt); assert(cxt->label); assert(fdisk_is_disklabel(cxt, SUN)); sunlabel = self_disklabel(cxt); if (i >= cxt->label->nparts_max || !t || t->type > UINT16_MAX) return -EINVAL; if (i == 2 && t->type != SUN_TAG_WHOLEDISK) fdisk_info(cxt, _("Consider leaving partition 3 as Whole disk (5),\n" "as SunOS/Solaris expects it and even Linux likes it.\n")); part = &sunlabel->partitions[i]; info = &sunlabel->vtoc.infos[i]; if (t->type == SUN_TAG_LINUX_SWAP && !part->start_cylinder) { int yes, rc; rc = fdisk_ask_yesno(cxt, _("It is highly recommended that the partition at offset 0\n" "is UFS, EXT2FS filesystem or SunOS swap. Putting Linux swap\n" "there may destroy your partition table and bootblock.\n" "Are you sure you want to tag the partition as Linux swap?"), &yes); if (rc) return rc; if (!yes) return 1; } switch (t->type) { case SUN_TAG_SWAP: case SUN_TAG_LINUX_SWAP: /* swaps are not mountable by default */ info->flags |= cpu_to_be16(SUN_FLAG_UNMNT); break; default: /* assume other types are mountable; user can change it anyway */ info->flags &= ~cpu_to_be16(SUN_FLAG_UNMNT); break; } info->id = cpu_to_be16(t->type); return 0; }
static void fetch_sun(struct fdisk_context *cxt, uint32_t *starts, uint32_t *lens, uint32_t *start, uint32_t *stop) { struct sun_disklabel *sunlabel; int continuous = 1; size_t i; assert(cxt); assert(cxt); assert(cxt->label); assert(fdisk_is_disklabel(cxt, SUN)); sunlabel = self_disklabel(cxt); *start = 0; *stop = cxt->geom.cylinders * cxt->geom.heads * cxt->geom.sectors; for (i = 0; i < cxt->label->nparts_max; i++) { struct sun_partition *part = &sunlabel->partitions[i]; struct sun_info *info = &sunlabel->vtoc.infos[i]; if (part->num_sectors && be16_to_cpu(info->id) != SUN_TAG_UNASSIGNED && be16_to_cpu(info->id) != SUN_TAG_WHOLEDISK) { starts[i] = be32_to_cpu(part->start_cylinder) * cxt->geom.heads * cxt->geom.sectors; lens[i] = be32_to_cpu(part->num_sectors); if (continuous) { if (starts[i] == *start) *start += lens[i]; else if (starts[i] + lens[i] >= *stop) *stop = starts[i]; else continuous = 0; /* There will be probably more gaps than one, so lets check afterwards */ } } else { starts[i] = 0; lens[i] = 0; } } }
void toggle_dos_compatibility_flag(struct fdisk_context *cxt) { struct fdisk_label *lb = fdisk_context_get_label(cxt, "dos"); int flag; if (!lb) return; flag = !fdisk_dos_is_compatible(lb); fdisk_info(cxt, flag ? _("DOS Compatibility flag is set (DEPRECATED!)") : _("DOS Compatibility flag is not set")); fdisk_dos_enable_compatible(lb, flag); if (fdisk_is_disklabel(cxt, DOS)) fdisk_reset_alignment(cxt); /* reset the current label */ }
static int sgi_write_disklabel(struct fdisk_context *cxt) { struct sgi_disklabel *sgilabel; struct sgi_info *info = NULL; assert(cxt); assert(cxt->label); assert(fdisk_is_disklabel(cxt, SGI)); sgilabel = self_disklabel(cxt); sgilabel->csum = 0; sgilabel->csum = cpu_to_be32(sgi_pt_checksum(sgilabel)); assert(sgi_pt_checksum(sgilabel) == 0); if (lseek(cxt->dev_fd, 0, SEEK_SET) < 0) goto err; if (write_all(cxt->dev_fd, sgilabel, DEFAULT_SECTOR_SIZE)) goto err; if (!strncmp((char *) sgilabel->volume[0].name, "sgilabel", 8)) { /* * keep this habit of first writing the "sgilabel". * I never tested whether it works without (AN 981002). */ int infostartblock = be32_to_cpu(sgilabel->volume[0].block_num); if (lseek(cxt->dev_fd, (off_t) infostartblock * DEFAULT_SECTOR_SIZE, SEEK_SET) < 0) goto err; info = sgi_new_info(); if (!info) goto err; if (write_all(cxt->dev_fd, info, sizeof(*info))) goto err; } sgi_free_info(info); return 0; err: sgi_free_info(info); return -errno; }
static int bsd_list_disklabel(struct fdisk_context *cxt) { struct bsd_disklabel *d = self_disklabel(cxt); assert(cxt); assert(cxt->label); assert(fdisk_is_disklabel(cxt, BSD)); if (fdisk_context_display_details(cxt)) { fdisk_info(cxt, "# %s:", cxt->dev_path); if ((unsigned) d->d_type < BSD_DKMAXTYPES) fdisk_info(cxt, _("type: %s"), bsd_dktypenames[d->d_type]); else fdisk_info(cxt, _("type: %d"), d->d_type); fdisk_info(cxt, _("disk: %.*s"), (int) sizeof(d->d_typename), d->d_typename); fdisk_info(cxt, _("label: %.*s"), (int) sizeof(d->d_packname), d->d_packname); fdisk_info(cxt, _("flags: %s"), d->d_flags & BSD_D_REMOVABLE ? _(" removable") : d->d_flags & BSD_D_ECC ? _(" ecc") : d->d_flags & BSD_D_BADSECT ? _(" badsect") : ""); /* On various machines the fields of *lp are short/int/long */ /* In order to avoid problems, we cast them all to long. */ fdisk_info(cxt, _("bytes/sector: %ld"), (long) d->d_secsize); fdisk_info(cxt, _("sectors/track: %ld"), (long) d->d_nsectors); fdisk_info(cxt, _("tracks/cylinder: %ld"), (long) d->d_ntracks); fdisk_info(cxt, _("sectors/cylinder: %ld"), (long) d->d_secpercyl); fdisk_info(cxt, _("cylinders: %ld"), (long) d->d_ncylinders); fdisk_info(cxt, _("rpm: %d"), d->d_rpm); fdisk_info(cxt, _("interleave: %d"), d->d_interleave); fdisk_info(cxt, _("trackskew: %d"), d->d_trackskew); fdisk_info(cxt, _("cylinderskew: %d"), d->d_cylskew); fdisk_info(cxt, _("headswitch: %ld (milliseconds)"), (long) d->d_headswitch); fdisk_info(cxt, _("track-to-track seek: %ld (milliseconds)"), (long) d->d_trkseek); } fdisk_info(cxt, _("partitions: %d"), d->d_npartitions); return 0; }
static struct fdisk_parttype *sun_get_parttype( struct fdisk_context *cxt, size_t n) { struct sun_disklabel *sunlabel = self_disklabel(cxt); struct fdisk_parttype *t; assert(cxt); assert(cxt->label); assert(fdisk_is_disklabel(cxt, SUN)); if (n >= cxt->label->nparts_max) return NULL; t = fdisk_get_parttype_from_code(cxt, be16_to_cpu(sunlabel->vtoc.infos[n].id)); if (!t) t = fdisk_new_unknown_parttype(be16_to_cpu(sunlabel->vtoc.infos[n].id), NULL); return t; }
static int sgi_get_partition_status( struct fdisk_context *cxt, size_t i, int *status) { assert(cxt); assert(fdisk_is_disklabel(cxt, SGI)); if (!status || i >= cxt->label->nparts_max) return -EINVAL; *status = FDISK_PARTSTAT_NONE; if (sgi_get_num_sectors(cxt, i)) *status = FDISK_PARTSTAT_USED; return 0; }
/* * 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_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; }
int main(int argc, char **argv) { int i, c, act = ACT_FDISK; int colormode = UL_COLORMODE_AUTO; struct fdisk_context *cxt; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); atexit(close_stdout); fdisk_init_debug(0); cxt = fdisk_new_context(); if (!cxt) err(EXIT_FAILURE, _("failed to allocate libfdisk context")); fdisk_context_set_ask(cxt, ask_callback, NULL); while ((c = getopt(argc, argv, "b:c::C:hH:lL::sS:t:u::vV")) != -1) { switch (c) { case 'b': { size_t sz = strtou32_or_err(optarg, _("invalid sector size argument")); if (sz != 512 && sz != 1024 && sz != 2048 && sz != 4096) usage(stderr); fdisk_save_user_sector_size(cxt, sz, sz); break; } case 'C': fdisk_save_user_geometry(cxt, strtou32_or_err(optarg, _("invalid cylinders argument")), 0, 0); break; case 'c': if (optarg) { /* this setting is independent on the current * actively used label */ struct fdisk_label *lb = fdisk_context_get_label(cxt, "dos"); if (!lb) err(EXIT_FAILURE, _("not found DOS label driver")); if (strcmp(optarg, "=dos") == 0) fdisk_dos_enable_compatible(lb, TRUE); else if (strcmp(optarg, "=nondos") == 0) fdisk_dos_enable_compatible(lb, FALSE); else usage(stderr); } /* use default if no optarg specified */ break; case 'H': fdisk_save_user_geometry(cxt, 0, strtou32_or_err(optarg, _("invalid heads argument")), 0); break; case 'S': fdisk_save_user_geometry(cxt, 0, 0, strtou32_or_err(optarg, _("invalid sectors argument"))); break; case 'l': act = ACT_LIST; break; case 'L': if (optarg) colormode = colormode_or_err(optarg, _("unsupported color mode")); break; case 's': act = ACT_SHOWSIZE; break; case 't': { struct fdisk_label *lb = NULL; while (fdisk_context_next_label(cxt, &lb) == 0) fdisk_label_set_disabled(lb, 1); lb = fdisk_context_get_label(cxt, optarg); if (!lb) errx(EXIT_FAILURE, _("unsupported disklabel: %s"), optarg); fdisk_label_set_disabled(lb, 0); } case 'u': if (optarg && *optarg == '=') optarg++; if (fdisk_context_set_unit(cxt, optarg) != 0) usage(stderr); break; case 'V': case 'v': printf(UTIL_LINUX_VERSION); return EXIT_SUCCESS; case 'h': usage(stdout); default: usage(stderr); } } if (argc-optind != 1 && fdisk_has_user_device_properties(cxt)) warnx(_("The device properties (sector size and geometry) should" " be used with one specified device only.")); colors_init(colormode); switch (act) { case ACT_LIST: fdisk_context_enable_listonly(cxt, 1); if (argc > optind) { int k; for (k = optind; k < argc; k++) print_device_pt(cxt, argv[k]); } else print_all_devices_pt(cxt); break; case ACT_SHOWSIZE: /* deprecated */ if (argc - optind <= 0) usage(stderr); for (i = optind; i < argc; i++) { if (argc - optind == 1) printf("%llu\n", get_dev_blocks(argv[i])); else printf("%s: %llu\n", argv[i], get_dev_blocks(argv[i])); } break; case ACT_FDISK: if (argc-optind != 1) usage(stderr); /* Here starts interactive mode, use fdisk_{warn,info,..} functions */ color_enable(UL_COLOR_GREEN); fdisk_info(cxt, _("Welcome to fdisk (%s)."), PACKAGE_STRING); color_disable(); fdisk_info(cxt, _("Changes will remain in memory only, until you decide to write them.\n" "Be careful before using the write command.\n")); if (fdisk_context_assign_device(cxt, argv[optind], 0) != 0) err(EXIT_FAILURE, _("cannot open %s"), argv[optind]); fflush(stdout); if (!fdisk_dev_has_disklabel(cxt)) { fdisk_info(cxt, _("Device does not contain a recognized partition table.")); fdisk_create_disklabel(cxt, NULL); } else if (fdisk_is_disklabel(cxt, GPT) && fdisk_gpt_is_hybrid(cxt)) fdisk_warnx(cxt, _( "The hybrid GPT detected. You have to sync " "the hybrid MBR manually (expert command 'M').")); while (1) process_fdisk_menu(&cxt); } fdisk_free_context(cxt); return EXIT_SUCCESS; }
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) { 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; }
static int sun_verify_disklabel(struct fdisk_context *cxt) { uint32_t starts[SUN_MAXPARTITIONS], lens[SUN_MAXPARTITIONS], start, stop; uint32_t i,j,k,starto,endo; int array[SUN_MAXPARTITIONS]; unsigned int *verify_sun_starts; assert(cxt); assert(cxt->label); assert(fdisk_is_disklabel(cxt, SUN)); verify_sun_starts = starts; fetch_sun(cxt, starts, lens, &start, &stop); for (k = 0; k < 7; k++) { for (i = 0; i < SUN_MAXPARTITIONS; i++) { if (k && (lens[i] % (cxt->geom.heads * cxt->geom.sectors))) fdisk_warnx(cxt, _("Partition %u doesn't end on cylinder boundary."), i+1); if (lens[i]) { for (j = 0; j < i; j++) if (lens[j]) { if (starts[j] == starts[i]+lens[i]) { starts[j] = starts[i]; lens[j] += lens[i]; lens[i] = 0; } else if (starts[i] == starts[j]+lens[j]){ lens[j] += lens[i]; lens[i] = 0; } else if (!k) { if (starts[i] < starts[j]+lens[j] && starts[j] < starts[i]+lens[i]) { starto = starts[i]; if (starts[j] > starto) starto = starts[j]; endo = starts[i]+lens[i]; if (starts[j]+lens[j] < endo) endo = starts[j]+lens[j]; fdisk_warnx(cxt, _("Partition %u overlaps with others in " "sectors %u-%u."), i+1, starto, endo); } } } } } } for (i = 0; i < SUN_MAXPARTITIONS; i++) { if (lens[i]) array[i] = i; else array[i] = -1; } qsort_r(array,ARRAY_SIZE(array),sizeof(array[0]), (int (*)(const void *,const void *,void *)) verify_sun_cmp, verify_sun_starts); if (array[0] == -1) { fdisk_info(cxt, _("No partitions defined.")); return 0; } stop = cxt->geom.cylinders * cxt->geom.heads * cxt->geom.sectors; if (starts[array[0]]) fdisk_warnx(cxt, _("Unused gap - sectors 0-%u."), starts[array[0]]); for (i = 0; i < 7 && array[i+1] != -1; i++) { fdisk_warnx(cxt, _("Unused gap - sectors %u-%u."), (starts[array[i]] + lens[array[i]]), starts[array[i+1]]); } start = (starts[array[i]] + lens[array[i]]); if (start < stop) fdisk_warnx(cxt, _("Unused gap - sectors %u-%u."), start, stop); return 0; }
static int verify_disklabel(struct fdisk_context *cxt, int verbose) { int Index[SGI_MAXPARTITIONS]; /* list of valid partitions */ int sortcount = 0; /* number of used partitions, i.e. non-zero lengths */ int entire = 0, i = 0; unsigned int start = 0; long long gap = 0; /* count unused blocks */ unsigned int lastblock = sgi_get_lastblock(cxt); assert(cxt); assert(cxt->label); assert(fdisk_is_disklabel(cxt, SGI)); clear_freelist(cxt); memset(Index, 0, sizeof(Index)); for (i=0; i < SGI_MAXPARTITIONS; i++) { if (sgi_get_num_sectors(cxt, i) != 0) { Index[sortcount++] = i; if (sgi_get_sysid(cxt, i) == SGI_TYPE_ENTIRE_DISK && entire++ == 1) { if (verbose) fdisk_info(cxt, _("More than one entire " "disk entry present.")); } } } if (sortcount == 0) { if (verbose) fdisk_info(cxt, _("No partitions defined")); return (lastblock > 0) ? 1 : (lastblock == 0) ? 0 : -1; } sort(Index, sortcount, sizeof(Index[0]), cxt, compare_start); if (sgi_get_sysid(cxt, Index[0]) == SGI_TYPE_ENTIRE_DISK) { if (verbose && Index[0] != 10) fdisk_info(cxt, _("IRIX likes when Partition 11 " "covers the entire disk.")); if (verbose && sgi_get_start_sector(cxt, Index[0]) != 0) fdisk_info(cxt, _("The entire disk partition should " "start at block 0, not at diskblock %d."), sgi_get_start_sector(cxt, Index[0])); if (verbose && sgi_get_num_sectors(cxt, Index[0]) != lastblock) DBG(LABEL, dbgprint( "entire disk partition=%ds, but disk=%ds", sgi_get_num_sectors(cxt, Index[0]), lastblock)); lastblock = sgi_get_num_sectors(cxt, Index[0]); } else if (verbose) { fdisk_info(cxt, _("Partition 11 should cover the entire disk.")); DBG(LABEL, dbgprint("sysid=%d\tpartition=%d", sgi_get_sysid(cxt, Index[0]), Index[0]+1)); } for (i=1, start=0; i<sortcount; i++) { int cylsize = sgi_get_nsect(cxt) * sgi_get_ntrks(cxt); if (verbose && cylsize && (sgi_get_start_sector(cxt, Index[i]) % cylsize) != 0) DBG(LABEL, dbgprint("partition %d does not start on " "cylinder boundary.", Index[i]+1)); if (verbose && cylsize && sgi_get_num_sectors(cxt, Index[i]) % cylsize != 0) DBG(LABEL, dbgprint("partition %d does not end on " "cylinder boundary.", Index[i]+1)); /* We cannot handle several "entire disk" entries. */ if (sgi_get_sysid(cxt, Index[i]) == SGI_TYPE_ENTIRE_DISK) continue; if (start > sgi_get_start_sector(cxt, Index[i])) { if (verbose) fdisk_info(cxt, _("The Partition %d and %d overlap " "by %d sectors."), Index[i-1]+1, Index[i]+1, start - sgi_get_start_sector(cxt, Index[i])); if (gap > 0) gap = -gap; if (gap == 0) gap = -1; } if (start < sgi_get_start_sector(cxt, Index[i])) { if (verbose) fdisk_info(cxt, _("Unused gap of %8u sectors " "- sectors %8u-%u"), sgi_get_start_sector(cxt, Index[i]) - start, start, sgi_get_start_sector(cxt, Index[i])-1); gap += sgi_get_start_sector(cxt, Index[i]) - start; add_to_freelist(cxt, start, sgi_get_start_sector(cxt, Index[i])); } start = sgi_get_start_sector(cxt, Index[i]) + sgi_get_num_sectors(cxt, Index[i]); /* Align free space on cylinder boundary */ if (cylsize && start % cylsize) start += cylsize - (start % cylsize); DBG(LABEL, dbgprint("%2d:%12d\t%12d\t%12d", Index[i], sgi_get_start_sector(cxt, Index[i]), sgi_get_num_sectors(cxt, Index[i]), sgi_get_sysid(cxt, Index[i]))); } if (start < lastblock) { if (verbose) fdisk_info(cxt, _("Unused gap of %8u sectors - sectors %8u-%u"), lastblock - start, start, lastblock-1); gap += lastblock - start; add_to_freelist(cxt, start, lastblock); } /* * Done with arithmetics. Go for details now */ if (verbose) { if (sgi_get_bootpartition(cxt) < 0 || !sgi_get_num_sectors(cxt, sgi_get_bootpartition(cxt))) fdisk_info(cxt, _("The boot partition does not exist.")); if (sgi_get_swappartition(cxt) < 0 || !sgi_get_num_sectors(cxt, sgi_get_swappartition(cxt))) fdisk_info(cxt, _("The swap partition does not exist.")); else if (sgi_get_sysid(cxt, sgi_get_swappartition(cxt)) != SGI_TYPE_SWAP && sgi_get_sysid(cxt, sgi_get_swappartition(cxt)) != MBR_LINUX_SWAP_PARTITION) fdisk_info(cxt, _("The swap partition has no swap type.")); if (sgi_check_bootfile(cxt, "/unix")) fdisk_info(cxt, _("You have chosen an unusual boot " "file name.")); } return (gap > 0) ? 1 : (gap == 0) ? 0 : -1; }
static int sun_list_disklabel(struct fdisk_context *cxt) { struct sun_disklabel *sunlabel; struct tt *tb = NULL; size_t i; int rc; assert(cxt); assert(cxt->label); assert(fdisk_is_disklabel(cxt, SUN)); sunlabel = self_disklabel(cxt); if (fdisk_context_display_details(cxt)) { fdisk_colon(cxt, _("Label geometry: %d rpm, %d alternate and %d physical cylinders,\n" " %d extra sects/cyl, interleave %d:1"), be16_to_cpu(sunlabel->rpm), be16_to_cpu(sunlabel->acyl), be16_to_cpu(sunlabel->pcyl), be16_to_cpu(sunlabel->apc), be16_to_cpu(sunlabel->intrlv)); fdisk_colon(cxt, _("Label ID: %s"), sunlabel->label_id); fdisk_colon(cxt, _("Volume ID: %s"), *sunlabel->vtoc.volume_id ? sunlabel->vtoc.volume_id : _("<none>")); } tb = tt_new_table(TT_FL_FREEDATA); if (!tb) return -ENOMEM; tt_define_column(tb, _("Device"), 0.2, 0); tt_define_column(tb, _("Flag"), 2, TT_FL_RIGHT); tt_define_column(tb, _("Start"), 9, TT_FL_RIGHT); tt_define_column(tb, _("End"), 9, TT_FL_RIGHT); /* TRANSLATORS: keep one blank space behind 'Blocks' */ tt_define_column(tb, _("Blocks "), 9, TT_FL_RIGHT); tt_define_column(tb, _("Id"), 2, TT_FL_RIGHT); tt_define_column(tb, _("System"), 0.2, TT_FL_TRUNC); for (i = 0 ; i < cxt->label->nparts_max; i++) { struct sun_partition *part = &sunlabel->partitions[i]; uint16_t flags = be16_to_cpu(sunlabel->vtoc.infos[i].flags); uint32_t start, len; struct fdisk_parttype *t; struct tt_line *ln; char *p; if (!part->num_sectors) continue; ln = tt_add_line(tb, NULL); if (!ln) continue; start = be32_to_cpu(part->start_cylinder) * cxt->geom.heads * cxt->geom.sectors; len = be32_to_cpu(part->num_sectors); t = fdisk_get_partition_type(cxt, i); p = fdisk_partname(cxt->dev_path, i + 1); if (p) tt_line_set_data(ln, 0, p); /* devname */ if ((flags & SUN_FLAG_UNMNT || flags & SUN_FLAG_RONLY) && asprintf(&p, "%c%c", flags & SUN_FLAG_UNMNT ? 'u' : ' ', flags & SUN_FLAG_RONLY ? 'r' : ' ') > 0) tt_line_set_data(ln, 1, p); /* flags */ if (asprintf(&p, "%ju", (uintmax_t) fdisk_scround(cxt, start)) > 0) tt_line_set_data(ln, 2, p); /* start */ if (asprintf(&p, "%ju", (uintmax_t) fdisk_scround(cxt, start + len - 1)) > 0) tt_line_set_data(ln, 3, p); /* end */ if (asprintf(&p, "%lu%c", (unsigned long) len / 2, len & 1 ? '+' : ' ') > 0) tt_line_set_data(ln, 4, p); /* blocks + flag */ if (asprintf(&p, "%2x", t->type) > 0) tt_line_set_data(ln, 5, p); /* type ID */ if (t->name) tt_line_set_data(ln, 6, strdup(t->name)); /* type Name */ fdisk_free_parttype(t); } rc = fdisk_print_table(cxt, tb); tt_free_table(tb); return rc; }
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_disklabel(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; }