/** * fdisk_set_partition: * @cxt: context * @partno: partition number (0 is the first partition) * @pa: new partition setting * * Modifies disklabel according to setting with in @pa. * * Returns: 0 on success, <0 on error. */ int fdisk_set_partition(struct fdisk_context *cxt, size_t partno, struct fdisk_partition *pa) { struct fdisk_partition *xpa = pa; int rc; if (!cxt || !cxt->label || !pa) return -EINVAL; if (!cxt->label->op->set_part) return -ENOSYS; if (pa->resize || fdisk_partition_has_start(pa) || fdisk_partition_has_size(pa)) { xpa = __copy_partition(pa); xpa->movestart = 0; xpa->resize = 0; FDISK_INIT_UNDEF(xpa->size); FDISK_INIT_UNDEF(xpa->start); rc = recount_resize(cxt, partno, xpa, pa); if (rc) goto done; } DBG(CXT, ul_debugobj(cxt, "setting partition %zu %p (start=%ju, end=%ju, size=%ju)", partno, xpa, (uintmax_t) fdisk_partition_get_start(xpa), (uintmax_t) fdisk_partition_get_end(xpa), (uintmax_t) fdisk_partition_get_size(xpa))); rc = cxt->label->op->set_part(cxt, partno, xpa); done: if (xpa != pa) fdisk_unref_partition(xpa); return rc; }
/** * fdisk_add_partition: * @cxt: fdisk context * @pa: template for the partition (or NULL) * @partno: NULL or returns new partition number * * If @pa is not specified or any @pa item is missiong the libfdisk will ask by * fdisk_ask_ API. * * Adds a new partition to disklabel. * * Returns: 0 on success, <0 on error. */ int fdisk_add_partition(struct fdisk_context *cxt, struct fdisk_partition *pa, size_t *partno) { int rc; assert(cxt); assert(cxt->label); if (!cxt || !cxt->label) return -EINVAL; if (!cxt->label->op->add_part) return -ENOSYS; if (fdisk_missing_geometry(cxt)) return -EINVAL; if (pa) DBG(CXT, ul_debugobj(cxt, "adding new partition %p (start=%ju, end=%ju, size=%ju, " "defaults(start=%s, end=%s, partno=%s)", pa, (uintmax_t) fdisk_partition_get_start(pa), (uintmax_t) fdisk_partition_get_end(pa), (uintmax_t) fdisk_partition_get_size(pa), pa->start_follow_default ? "yes" : "no", pa->end_follow_default ? "yes" : "no", pa->partno_follow_default ? "yes" : "no")); else DBG(CXT, ul_debugobj(cxt, "adding partition")); rc = cxt->label->op->add_part(cxt, pa, partno); DBG(CXT, ul_debugobj(cxt, "add partition done (rc=%d)", rc)); return rc; }
/** * fdisk_set_partition: * @cxt: context * @partno: partition number (0 is the first partition) * @pa: new partition setting * * Modifies disklabel according to setting with in @pa. * * Returns: 0 on success, <0 on error. */ int fdisk_set_partition(struct fdisk_context *cxt, size_t partno, struct fdisk_partition *pa) { if (!cxt || !cxt->label || !pa) return -EINVAL; if (!cxt->label->op->set_part) return -ENOSYS; DBG(CXT, ul_debugobj(cxt, "setting partition %zu %p (start=%ju, end=%ju, size=%ju, " "defaults(start=%s, end=%s, partno=%s)", partno, pa, (uintmax_t) fdisk_partition_get_start(pa), (uintmax_t) fdisk_partition_get_end(pa), (uintmax_t) fdisk_partition_get_size(pa), pa->start_follow_default ? "yes" : "no", pa->end_follow_default ? "yes" : "no", pa->partno_follow_default ? "yes" : "no")); return cxt->label->op->set_part(cxt, partno, pa); }
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); }
/* * 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; }