static int sgi_check_bootfile(struct fdisk_context *cxt, const char *name) { size_t sz; struct sgi_disklabel *sgilabel = self_disklabel(cxt); sz = strlen(name); if (sz < 3) { /* "/a\n" is minimum */ fdisk_warnx(cxt, _("Invalid Bootfile! " "The bootfile must be an absolute non-zero pathname," "e.g. \"/unix\" or \"/unix.save\".")); return -EINVAL; } else if (sz > sizeof(sgilabel->boot_file)) { fdisk_warnx(cxt, _("Name of Bootfile too long: %zu bytes maximum."), sizeof(sgilabel->boot_file)); return -EINVAL; } else if (*name != '/') { fdisk_warnx(cxt, _("Bootfile must have a fully qualified pathname.")); return -EINVAL; } if (strncmp(name, (char *) sgilabel->boot_file, sizeof(sgilabel->boot_file))) { fdisk_warnx(cxt, _("Be aware, that the bootfile is not checked " "for existence. SGI's default is \"/unix\" and for " "backup \"/unix.save\".")); /* filename is correct and did change */ return 0; } return 1; /* filename did not change */ }
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; }
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); }
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 sgi_set_partition(struct fdisk_context *cxt, size_t i, struct fdisk_partition *pa) { struct sgi_disklabel *sgilabel; if (i >= cxt->label->nparts_max) return -EINVAL; sgilabel = self_disklabel(cxt); if (pa->type) { struct fdisk_parttype *t = pa->type; if (sgi_get_num_sectors(cxt, i) == 0) /* caught already before, ... */ { fdisk_warnx(cxt, _("Sorry, only for non-empty partitions you can change the tag.")); return -EINVAL; } if ((i == 10 && t->code != SGI_TYPE_ENTIRE_DISK) || (i == 8 && t->code != 0)) fdisk_info(cxt, _("Consider leaving partition 9 as volume header (0), " "and partition 11 as entire volume (6), " "as IRIX expects it.")); if (cxt->script == NULL && ((t->code != SGI_TYPE_ENTIRE_DISK) && (t->code != SGI_TYPE_VOLHDR)) && (sgi_get_start_sector(cxt, i) < 1)) { int yes = 0; fdisk_ask_yesno(cxt, _("It is highly recommended that the partition at offset 0 " "is of type \"SGI volhdr\", the IRIX system will rely on it to " "retrieve from its directory standalone tools like sash and fx. " "Only the \"SGI volume\" entire disk section may violate this. " "Are you sure about tagging this partition differently?"), &yes); if (!yes) return 1; } sgilabel->partitions[i].type = cpu_to_be32(t->code); } if (fdisk_partition_has_start(pa)) sgilabel->partitions[i].first_block = cpu_to_be32(pa->start); if (fdisk_partition_has_size(pa)) sgilabel->partitions[i].num_blocks = cpu_to_be32(pa->size); fdisk_label_set_changed(cxt->label, 1); return 0; }
/* * Read a bsd_disklabel from sector 0 or from the starting sector of p. * If it has the right magic, return 0. */ static int bsd_readlabel(struct fdisk_context *cxt) { struct fdisk_bsd_label *l; struct bsd_disklabel *d; int t; off_t offset = 0; l = self_label(cxt); d = self_disklabel(cxt); if (l->dos_part) /* BSD is nested within DOS partition, get the begin of the * partition. Note that DOS uses native sector size. */ offset = dos_partition_get_start(l->dos_part) * cxt->sector_size; if (lseek(cxt->dev_fd, offset, SEEK_SET) == -1) return -1; if (read_all(cxt->dev_fd, l->bsdbuffer, sizeof(l->bsdbuffer)) < 0) return errno ? -errno : -1; /* The offset to begin of the disk label. Note that BSD uses * 512-byte (default) sectors. */ memmove(d, &l->bsdbuffer[BSD_LABELSECTOR * DEFAULT_SECTOR_SIZE + BSD_LABELOFFSET], sizeof(*d)); if (d->d_magic != BSD_DISKMAGIC || d->d_magic2 != BSD_DISKMAGIC) { DBG(LABEL, ul_debug("not found magic")); return -1; } for (t = d->d_npartitions; t < BSD_MAXPARTITIONS; t++) { d->d_partitions[t].p_size = 0; d->d_partitions[t].p_offset = 0; d->d_partitions[t].p_fstype = BSD_FS_UNUSED; } if (d->d_npartitions > BSD_MAXPARTITIONS) fdisk_warnx(cxt, ("Too many partitions (%d, maximum is %d)."), d->d_npartitions, BSD_MAXPARTITIONS); /* let's follow in-PT geometry */ cxt->geom.sectors = d->d_nsectors; cxt->geom.heads = d->d_ntracks; cxt->geom.cylinders = d->d_ncylinders; cxt->label->nparts_cur = d->d_npartitions; cxt->label->nparts_max = BSD_MAXPARTITIONS; DBG(LABEL, ul_debug("read BSD label")); return 0; }
/* * look for DOS partition usable for nested BSD partition table */ static int bsd_assign_dos_partition(struct fdisk_context *cxt) { struct fdisk_bsd_label *l = self_label(cxt); size_t i; for (i = 0; i < 4; i++) { sector_t ss; l->dos_part = fdisk_dos_get_partition(cxt->parent, i); if (!l->dos_part || !is_bsd_partition_type(l->dos_part->sys_ind)) continue; ss = dos_partition_get_start(l->dos_part); if (!ss) { fdisk_warnx(cxt, _("Partition %zd: has invalid starting " "sector 0."), i + 1); return -1; } if (cxt->parent->dev_path) { free(cxt->dev_path); cxt->dev_path = fdisk_partname( cxt->parent->dev_path, i + 1); } DBG(LABEL, ul_debug("partition %zu assigned to BSD", i + 1)); return 0; } fdisk_warnx(cxt, _("There is no *BSD partition on %s."), cxt->parent->dev_path); free(cxt->dev_path); cxt->dev_path = NULL; l->dos_part = NULL; return 1; }
int fdisk_missing_geometry(struct fdisk_context *cxt) { int rc; assert(cxt); rc = (fdisk_require_geometry(cxt) && (!cxt->geom.heads || !cxt->geom.sectors || !cxt->geom.cylinders)); if (rc && !fdisk_context_listonly(cxt)) fdisk_warnx(cxt, _("Incomplete geometry setting.")); return rc; }
/* * This function prints a warning if the device is not wiped (e.g. wipefs(8). * Please don't call this function if there is already a PT. * * Returns: 0 if nothing found, < 0 on error, 1 if found a signature */ static int warn_wipe(struct fdisk_context *cxt) { #ifdef HAVE_LIBBLKID blkid_probe pr; #endif int rc = 0; assert(cxt); if (fdisk_dev_has_disklabel(cxt) || cxt->dev_fd < 0) return -EINVAL; #ifdef HAVE_LIBBLKID DBG(LABEL, dbgprint("wipe check: initialize libblkid prober")); pr = blkid_new_probe(); if (!pr) return -ENOMEM; rc = blkid_probe_set_device(pr, cxt->dev_fd, 0, 0); if (rc) return rc; blkid_probe_enable_superblocks(pr, 1); blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_TYPE); blkid_probe_enable_partitions(pr, 1); /* we care about the first found FS/raid, so don't call blkid_do_probe() * in loop or don't use blkid_do_fullprobe() ... */ rc = blkid_do_probe(pr); if (rc == 0) { const char *name = NULL; if (blkid_probe_lookup_value(pr, "TYPE", &name, 0) == 0 || blkid_probe_lookup_value(pr, "PTTYPE", &name, 0) == 0) { fdisk_warnx(cxt, _( "%s: device contains a valid '%s' signature, it's " "strongly recommended to wipe the device by command wipefs(8) " "if this setup is unexpected to avoid " "possible collisions."), cxt->dev_path, name); rc = 1; } } blkid_free_probe(pr); #endif return rc; }
static int ask_menu(struct fdisk_context *cxt, struct fdisk_ask *ask, char *buf, size_t bufsz) { const char *q = fdisk_ask_get_query(ask); int dft = fdisk_ask_menu_get_default(ask); if (q) { fputs(q, stdout); /* print header */ fputc('\n', stdout); } do { char prompt[128]; int key, c, rc; const char *name, *desc; size_t i = 0; /* print menu items */ while (fdisk_ask_menu_get_item(ask, i++, &key, &name, &desc) == 0) fprintf(stdout, " %c %s (%s)\n", key, name, desc); /* ask for key */ snprintf(prompt, sizeof(prompt), _("Select (default %c): "), dft); rc = get_user_reply(cxt, prompt, buf, bufsz); if (rc) return rc; if (!*buf) { fdisk_info(cxt, _("Using default response %c."), dft); c = dft; } else c = tolower(buf[0]); /* check result */ i = 0; while (fdisk_ask_menu_get_item(ask, i++, &key, NULL, NULL) == 0) { if (c == key) { fdisk_ask_menu_set_result(ask, c); return 0; /* success */ } } fdisk_warnx(cxt, _("Value out of range.")); } while (1); return -EINVAL; }
/* * 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; }
void list_disklabel(struct fdisk_context *cxt) { struct fdisk_table *tb = NULL; struct fdisk_partition *pa = NULL; struct fdisk_iter *itr = NULL; struct fdisk_label *lb; struct libscols_table *out = NULL; const char *bold = NULL; int *ids = NULL; /* IDs of fdisk_fields */ size_t nids = 0, i; int post = 0; /* print label specific stuff by libfdisk FDISK_ASK_INFO API */ fdisk_list_disklabel(cxt); /* get partitions and generate output */ if (fdisk_get_partitions(cxt, &tb) || fdisk_table_get_nents(tb) <= 0) goto done; ids = init_fields(cxt, NULL, &nids); if (!ids) goto done; itr = fdisk_new_iter(FDISK_ITER_FORWARD); if (!itr) { fdisk_warn(cxt, _("faild to allocate iterator")); goto done; } out = scols_new_table(); if (!out) { fdisk_warn(cxt, _("faild to allocate output table")); goto done; } if (colors_wanted()) { scols_table_enable_colors(out, 1); bold = color_scheme_get_sequence("header", UL_COLOR_BOLD); } lb = fdisk_get_label(cxt, NULL); assert(lb); /* define output table columns */ for (i = 0; i < nids; i++) { int fl = 0; struct libscols_column *co; const struct fdisk_field *field = fdisk_label_get_field(lb, ids[i]); if (!field) continue; if (fdisk_field_is_number(field)) fl |= SCOLS_FL_RIGHT; if (fdisk_field_get_id(field) == FDISK_FIELD_TYPE) fl |= SCOLS_FL_TRUNC; co = scols_table_new_column(out, fdisk_field_get_name(field), fdisk_field_get_width(field), fl); if (!co) goto done; /* set colum header color */ if (bold) scols_cell_set_color(scols_column_get_header(co), bold); } /* fill-in output table */ while (fdisk_table_next_partition(tb, itr, &pa) == 0) { struct libscols_line *ln = scols_table_new_line(out, NULL); if (!ln) { fdisk_warn(cxt, _("faild to allocate output line")); goto done; } for (i = 0; i < nids; i++) { char *data = NULL; if (fdisk_partition_to_string(pa, cxt, ids[i], &data)) continue; scols_line_refer_data(ln, i, data); } } /* print */ if (!scols_table_is_empty(out)) { fputc('\n', stdout); scols_print_table(out); } /* print warnings */ fdisk_reset_iter(itr, FDISK_ITER_FORWARD); while (itr && fdisk_table_next_partition(tb, itr, &pa) == 0) { if (!fdisk_partition_has_start(pa)) continue; if (!fdisk_lba_is_phy_aligned(cxt, fdisk_partition_get_start(pa))) { if (!post) fputc('\n', stdout); fdisk_warnx(cxt, _("Partition %zu does not start on physical sector boundary."), fdisk_partition_get_partno(pa) + 1); post++; } } if (fdisk_table_wrong_order(tb)) { if (!post) fputc('\n', stdout); fdisk_info(cxt, _("Partition table entries are not in disk order.")); } done: scols_unref_table(out); fdisk_unref_table(tb); fdisk_free_iter(itr); }
static int ask_offset(struct fdisk_context *cxt, struct fdisk_ask *ask, char *buf, size_t bufsz) { char prompt[128] = { '\0' }; const char *q = fdisk_ask_get_query(ask); const char *range = fdisk_ask_number_get_range(ask); uint64_t dflt = fdisk_ask_number_get_default(ask), low = fdisk_ask_number_get_low(ask), high = fdisk_ask_number_get_high(ask), base = fdisk_ask_number_get_base(ask); assert(q); DBG(ASK, ul_debug("asking for offset ['%s', <%ju,%ju>, base=%ju, default=%ju, range: %s]", q, low, high, base, dflt, range)); if (range && dflt >= low && dflt <= high) snprintf(prompt, sizeof(prompt), _("%s (%s, default %ju): "), q, range, dflt); else if (dflt >= low && dflt <= high) snprintf(prompt, sizeof(prompt), _("%s (%ju-%ju, default %ju): "), q, low, high, dflt); else snprintf(prompt, sizeof(prompt), _("%s (%ju-%ju): "), q, low, high); do { uint64_t num = 0; char sig = 0, *p; int pwr = 0; int rc = get_user_reply(cxt, prompt, buf, bufsz); if (rc) return rc; if (!*buf && dflt >= low && dflt <= high) return fdisk_ask_number_set_result(ask, dflt); p = buf; if (*p == '+' || *p == '-') { sig = *buf; p++; } rc = parse_size(p, &num, &pwr); if (rc) continue; DBG(ASK, ul_debug("parsed size: %ju", num)); if (sig && pwr) { /* +{size}{K,M,...} specified, the "num" is in bytes */ uint64_t unit = fdisk_ask_number_get_unit(ask); num += unit/2; /* round */ num /= unit; } if (sig == '+') num += base; else if (sig == '-') num = base - num; DBG(ASK, ul_debug("final offset: %ju [sig: %c, power: %d, %s]", num, sig, pwr, sig ? "relative" : "absolute")); if (num >= low && num <= high) { if (sig) fdisk_ask_number_set_relative(ask, 1); return fdisk_ask_number_set_result(ask, num); } fdisk_warnx(cxt, _("Value out of range.")); } while (1); return -1; }
static int ask_number(struct fdisk_context *cxt, struct fdisk_ask *ask, char *buf, size_t bufsz) { char prompt[128] = { '\0' }; const char *q = fdisk_ask_get_query(ask); const char *range = fdisk_ask_number_get_range(ask); uint64_t dflt = fdisk_ask_number_get_default(ask), low = fdisk_ask_number_get_low(ask), high = fdisk_ask_number_get_high(ask); int inchar = fdisk_ask_number_inchars(ask); assert(q); DBG(ASK, ul_debug("asking for number " "['%s', <%ju,%ju>, default=%ju, range: %s]", q, low, high, dflt, range)); if (range && dflt >= low && dflt <= high) { if (inchar) snprintf(prompt, sizeof(prompt), _("%s (%s, default %c): "), q, range, tochar(dflt)); else snprintf(prompt, sizeof(prompt), _("%s (%s, default %ju): "), q, range, dflt); } else if (dflt >= low && dflt <= high) { if (inchar) snprintf(prompt, sizeof(prompt), _("%s (%c-%c, default %c): "), q, tochar(low), tochar(high), tochar(dflt)); else snprintf(prompt, sizeof(prompt), _("%s (%ju-%ju, default %ju): "), q, low, high, dflt); } else if (inchar) snprintf(prompt, sizeof(prompt), _("%s (%c-%c): "), q, tochar(low), tochar(high)); else snprintf(prompt, sizeof(prompt), _("%s (%ju-%ju): "), q, low, high); do { int rc = get_user_reply(cxt, prompt, buf, bufsz); uint64_t num; if (rc) return rc; if (!*buf && dflt >= low && dflt <= high) return fdisk_ask_number_set_result(ask, dflt); if (isdigit_string(buf)) { char *end; errno = 0; num = strtoumax(buf, &end, 10); if (errno || buf == end || (end && *end)) continue; } else if (inchar && isalpha(*buf)) { num = tolower(*buf) - 'a' + 1; } else rc = -EINVAL; if (rc == 0 && num >= low && num <= high) return fdisk_ask_number_set_result(ask, num); fdisk_warnx(cxt, _("Value out of range.")); } while (1); return -1; }
/* returns: 1=0 on success, < 0 on error, 1 if no free/used partition */ int fdisk_ask_partnum(struct fdisk_context *cxt, size_t *partnum, int wantnew) { int rc = 0, inchar = 0; char range[BUFSIZ], *ptr = range; size_t i, len = sizeof(range), begin = 0, run = 0; struct fdisk_ask *ask = NULL; __typeof__(ask->data.num) *num; assert(cxt); assert(cxt->label); assert(partnum); if (cxt->label && cxt->label->flags & FDISK_LABEL_FL_INCHARS_PARTNO) inchar = 1; DBG(ASK, dbgprint("%s: asking for %s partition number " "(max: %zd, inchar: %s)", cxt->label->name, wantnew ? "new" : "used", cxt->label->nparts_max, inchar ? "yes" : "not")); ask = fdisk_new_ask(); if (!ask) return -ENOMEM; fdisk_ask_set_type(ask, FDISK_ASKTYPE_NUMBER); num = &ask->data.num; ask->data.num.inchars = inchar ? 1 : 0; for (i = 0; i < cxt->label->nparts_max; i++) { int status = 0; rc = fdisk_partition_get_status(cxt, i, &status); if (rc) break; if (wantnew && !(status & FDISK_PARTSTAT_USED)) { ptr = mk_string_list(ptr, &len, &begin, &run, i, inchar); if (!ptr) { rc = -EINVAL; break; } if (!num->low) num->dfl = num->low = i + 1; num->hig = i + 1; } else if (!wantnew && (status & FDISK_PARTSTAT_USED)) { ptr = mk_string_list(ptr, &len, &begin, &run, i, inchar); if (!num->low) num->low = i + 1; num->dfl = num->hig = i + 1; } } DBG(ASK, dbgprint("ask limits: low: %zd, high: %zd, default: %zd", num->low, num->hig, num->dfl)); if (!rc && !wantnew && num->low == num->hig) { if (num->low > 0) { /* only one existing partiton, don't ask, return the number */ fdisk_ask_number_set_result(ask, num->low); fdisk_info(cxt, _("Selected partition %d"), num->low); } else if (num->low == 0) { fdisk_warnx(cxt, _("No partition is defined yet!")); rc = 1; } goto dont_ask; } if (!rc && wantnew && num->low == num->hig) { if (num->low > 0) { /* only one free partition, don't ask, return the number */ fdisk_ask_number_set_result(ask, num->low); fdisk_info(cxt, _("Selected partition %d"), num->low); } if (num->low == 0) { fdisk_warnx(cxt, _("No free partition available!")); rc = 1; } goto dont_ask; } if (!rc) { mk_string_list(ptr, &len, &begin, &run, -1, inchar); /* terminate the list */ rc = fdisk_ask_number_set_range(ask, range); } if (!rc) rc = fdisk_ask_set_query(ask, _("Partition number")); if (!rc) rc = fdisk_do_ask(cxt, ask); dont_ask: if (!rc) { *partnum = fdisk_ask_number_get_result(ask); if (*partnum) *partnum -= 1; } DBG(ASK, dbgprint("result: %zd [rc=%d]\n", fdisk_ask_number_get_result(ask), rc)); fdisk_free_ask(ask); return rc; }
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; #ifdef HAVE_QSORT_R int array[SUN_MAXPARTITIONS]; unsigned int *verify_sun_starts; #endif assert(cxt); assert(cxt->label); assert(fdisk_is_label(cxt, SUN)); 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); } } } } } } #ifdef HAVE_QSORT_R for (i = 0; i < SUN_MAXPARTITIONS; i++) { if (lens[i]) array[i] = i; else array[i] = -1; } verify_sun_starts = starts; 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); #endif return 0; }
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 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; }
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 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; }
/* * Uses template @tpl to recount start and size change of the partition @res. The * @tpl->size and @tpl->start are interpreted as relative to the current setting. */ static int recount_resize( struct fdisk_context *cxt, size_t partno, struct fdisk_partition *res, struct fdisk_partition *tpl) { fdisk_sector_t start, size; struct fdisk_partition *cur = NULL; struct fdisk_table *tb = NULL; int rc; DBG(PART, ul_debugobj(tpl, "resize requested")); FDISK_INIT_UNDEF(start); FDISK_INIT_UNDEF(size); rc = fdisk_get_partitions(cxt, &tb); if (!rc) rc = fdisk_get_freespaces(cxt, &tb); if (rc) return rc; cur = fdisk_table_get_partition_by_partno(tb, partno); if (!cur) { fdisk_unref_table(tb); return -EINVAL; } /* 1a) set new start - change relative to the current on-disk setting */ if (tpl->movestart && fdisk_partition_has_start(tpl)) { start = fdisk_partition_get_start(cur); if (tpl->movestart == FDISK_MOVE_DOWN) { if (fdisk_partition_get_start(tpl) > start) goto erange; start -= fdisk_partition_get_start(tpl); } else start += fdisk_partition_get_start(tpl); /* 1b) set new start - absolute number */ } else if (fdisk_partition_has_start(tpl)) start = fdisk_partition_get_start(tpl); /* 2) verify that start is within the current partition or any freespace area */ if (!FDISK_IS_UNDEF(start)) { struct fdisk_partition *area = resize_get_by_offset(tb, start); if (area == cur) DBG(PART, ul_debugobj(tpl, "resize: start points to the current partition")); else if (area && fdisk_partition_is_freespace(area)) DBG(PART, ul_debugobj(tpl, "resize: start points to freespace")); else if (!area && start >= cxt->first_lba && start < cxt->first_lba + (cxt->grain / cxt->sector_size)) DBG(PART, ul_debugobj(tpl, "resize: start points before first partition")); else goto erange; } else { /* no change, start points to the current partition */ start = fdisk_partition_get_start(cur); } /* 3a) set new size -- reduce */ if (tpl->resize == FDISK_RESIZE_REDUCE && fdisk_partition_has_size(tpl)) { DBG(PART, ul_debugobj(tpl, "resize: reduce")); size = fdisk_partition_get_size(cur); if (fdisk_partition_get_size(tpl) > size) goto erange; size -= fdisk_partition_get_size(tpl); /* 3b) set new size -- enlarge */ } else if (tpl->resize == FDISK_RESIZE_ENLARGE && fdisk_partition_has_size(tpl)) { DBG(PART, ul_debugobj(tpl, "resize: enlarge")); size = fdisk_partition_get_size(cur); size += fdisk_partition_get_size(tpl); /* 3c) set new size -- no size specified, enlarge to all freespace */ } else if (tpl->resize == FDISK_RESIZE_ENLARGE) { DBG(PART, ul_debugobj(tpl, "resize: enlarge to all possible")); if (resize_get_last_possible(tb, cur, start, &size)) goto erange; /* 3d) set new size -- absolute number */ } else if (fdisk_partition_has_size(tpl)) { DBG(PART, ul_debugobj(tpl, "resize: new absolute size")); size = fdisk_partition_get_size(tpl); } /* 4) verify that size is within the current partition or next free space */ if (!FDISK_IS_UNDEF(size)) { fdisk_sector_t maxsz; if (resize_get_last_possible(tb, cur, start, &maxsz)) goto erange; DBG(PART, ul_debugobj(tpl, "resize: size wanted=%ju, max=%ju", (uintmax_t) size, (uintmax_t) maxsz)); if (size > maxsz) goto erange; } DBG(PART, ul_debugobj(tpl, "resize: SUCCESS: start %ju->%ju; size %ju->%ju", (uintmax_t) fdisk_partition_get_start(cur), (uintmax_t) start, (uintmax_t) fdisk_partition_get_size(cur), (uintmax_t) size)); res->start = start; res->size = size; fdisk_unref_table(tb); return 0; erange: DBG(PART, ul_debugobj(tpl, "resize: FAILED")); fdisk_warnx(cxt, _("Failed to resize partition #%zu."), partno + 1); fdisk_unref_table(tb); return -ERANGE; }
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 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; }
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 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; }
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); if (fdisk_context_assign_device(cxt, argv[optind], 0) != 0) err(EXIT_FAILURE, _("cannot open %s"), argv[optind]); /* 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")); fflush(stdout); if (!fdisk_dev_has_disklabel(cxt)) { fdisk_warnx(cxt, _("Device does not contain a recognized partition table.")); fdisk_create_disklabel(cxt, NULL); } while (1) process_fdisk_menu(&cxt); } fdisk_free_context(cxt); return EXIT_SUCCESS; }