Module Name: src
Committed By: martin
Date: Tue Nov 12 16:33:14 UTC 2019
Modified Files:
src/usr.sbin/sysinst: bsddisklabel.c defs.h disklabel.c disks.c gpt.c
install.c label.c main.c mbr.c mbr.h msg.mi.de msg.mi.en msg.mi.es
msg.mi.fr msg.mi.pl part_edit.c partitions.c partitions.h util.c
src/usr.sbin/sysinst/arch/i386: md.c
Log Message:
Add options to the various partitioning stages that allow cloning of
alien partitions (optionally including data).
To generate a diff of this commit:
cvs rdiff -u -r1.29 -r1.30 src/usr.sbin/sysinst/bsddisklabel.c
cvs rdiff -u -r1.45 -r1.46 src/usr.sbin/sysinst/defs.h
cvs rdiff -u -r1.14 -r1.15 src/usr.sbin/sysinst/disklabel.c
cvs rdiff -u -r1.54 -r1.55 src/usr.sbin/sysinst/disks.c
cvs rdiff -u -r1.11 -r1.12 src/usr.sbin/sysinst/gpt.c \
src/usr.sbin/sysinst/install.c
cvs rdiff -u -r1.12 -r1.13 src/usr.sbin/sysinst/label.c
cvs rdiff -u -r1.17 -r1.18 src/usr.sbin/sysinst/main.c \
src/usr.sbin/sysinst/msg.mi.es
cvs rdiff -u -r1.21 -r1.22 src/usr.sbin/sysinst/mbr.c \
src/usr.sbin/sysinst/msg.mi.fr
cvs rdiff -u -r1.3 -r1.4 src/usr.sbin/sysinst/mbr.h
cvs rdiff -u -r1.16 -r1.17 src/usr.sbin/sysinst/msg.mi.de
cvs rdiff -u -r1.23 -r1.24 src/usr.sbin/sysinst/msg.mi.en
cvs rdiff -u -r1.24 -r1.25 src/usr.sbin/sysinst/msg.mi.pl
cvs rdiff -u -r1.10 -r1.11 src/usr.sbin/sysinst/part_edit.c
cvs rdiff -u -r1.4 -r1.5 src/usr.sbin/sysinst/partitions.c
cvs rdiff -u -r1.7 -r1.8 src/usr.sbin/sysinst/partitions.h
cvs rdiff -u -r1.34 -r1.35 src/usr.sbin/sysinst/util.c
cvs rdiff -u -r1.21 -r1.22 src/usr.sbin/sysinst/arch/i386/md.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/usr.sbin/sysinst/bsddisklabel.c
diff -u src/usr.sbin/sysinst/bsddisklabel.c:1.29 src/usr.sbin/sysinst/bsddisklabel.c:1.30
--- src/usr.sbin/sysinst/bsddisklabel.c:1.29 Fri Oct 25 12:24:34 2019
+++ src/usr.sbin/sysinst/bsddisklabel.c Tue Nov 12 16:33:14 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: bsddisklabel.c,v 1.29 2019/10/25 12:24:34 martin Exp $ */
+/* $NetBSD: bsddisklabel.c,v 1.30 2019/11/12 16:33:14 martin Exp $ */
/*
* Copyright 1997 Piermont Information Systems Inc.
@@ -251,6 +251,11 @@ draw_size_menu_line(menudesc *m, int opt
mount = swap;
} else if (pset->infos[opt].mount[0]) {
mount = pset->infos[opt].mount;
+ } else if (pset->infos[opt].flags & PUIFLG_CLONE_PARTS) {
+ snprintf(swap, sizeof swap, "%zu %s",
+ pset->infos[opt].clone_src->num_sel,
+ msg_string(MSG_clone_target_disp));
+ mount = swap;
} else {
mount = NULL;
if (pset->infos[opt].parts->pscheme->other_partition_identifier
@@ -319,7 +324,7 @@ add_other_ptn_size(menudesc *menu, void
break;
}
- m = realloc(pset->menu_opts, (pset->num+4)*sizeof(*pset->menu_opts));
+ m = realloc(pset->menu_opts, (pset->num+5)*sizeof(*pset->menu_opts));
if (m == NULL)
return 0;
p = realloc(pset->infos, (pset->num+1)*sizeof(*pset->infos));
@@ -348,6 +353,84 @@ add_other_ptn_size(menudesc *menu, void
return -1;
}
+static int
+inst_ext_clone(menudesc *menu, void *arg)
+{
+ struct selected_partitions selected;
+ struct clone_target_menu_data data;
+ struct partition_usage_set *pset = arg;
+ struct part_usage_info *p;
+ menu_ent *men;
+ int num_men, i;
+
+ if (!select_partitions(&selected, pm->parts))
+ return 0;
+
+ num_men = pset->num+1;
+ men = calloc(num_men, sizeof *men);
+ if (men == NULL)
+ return 0;
+ for (i = 0; i < num_men; i++)
+ men[i].opt_action = clone_target_select;
+ men[num_men-1].opt_name = MSG_clone_target_end;
+
+ memset(&data, 0, sizeof data);
+ data.usage = *pset;
+ data.res = -1;
+
+ data.usage.menu = new_menu(MSG_clone_target_hdr,
+ men, num_men, 3, 2, 0, 65, MC_SCROLL,
+ NULL, draw_size_menu_line, NULL, NULL, MSG_cancel);
+ process_menu(data.usage.menu, &data);
+ free_menu(data.usage.menu);
+ free(men);
+
+ if (data.res < 0)
+ goto err;
+
+ /* insert clone record */
+ men = realloc(pset->menu_opts, (pset->num+5)*sizeof(*pset->menu_opts));
+ if (men == NULL)
+ goto err;
+ pset->menu_opts = men;
+ menu->opts = men;
+ menu->numopts = pset->num+4;
+
+ p = realloc(pset->infos, (pset->num+1)*sizeof(*pset->infos));
+ if (p == NULL)
+ goto err;
+ pset->infos = p;
+
+ men += data.res;
+ p += data.res;
+ memmove(men+1, men, sizeof(*men)*((pset->num+4)-data.res));
+ memmove(p+1, p, sizeof(*p)*((pset->num)-data.res));
+ memset(men, 0, sizeof(*men));
+ memset(p, 0, sizeof(*p));
+ p->flags = PUIFLG_CLONE_PARTS;
+ p->cur_part_id = NO_PART;
+ p->clone_src = malloc(sizeof(selected));
+ if (p->clone_src != NULL) {
+ *p->clone_src = selected;
+ p->clone_ndx = ~0U;
+ p->size = selected_parts_size(&selected);
+ p->parts = pset->parts;
+ } else {
+ p->clone_ndx = 0;
+ free_selected_partitions(&selected);
+ }
+
+ menu->cursel = data.res == 0 ? 1 : 0;
+ pset->num++;
+ fill_ptn_menu(pset);
+
+ return -1;
+
+err:
+ free_selected_partitions(&selected);
+ return 0;
+}
+
static size_t
fill_ptn_menu(struct partition_usage_set *pset)
{
@@ -357,9 +440,12 @@ fill_ptn_menu(struct partition_usage_set
size_t i;
daddr_t free_space;
- memset(pset->menu_opts, 0, (pset->num+3)*sizeof(*pset->menu_opts));
+ memset(pset->menu_opts, 0, (pset->num+4)*sizeof(*pset->menu_opts));
for (m = pset->menu_opts, p = pset->infos, i = 0; i < pset->num;
m++, p++, i++) {
+ if (p->flags & PUIFLG_CLONE_PARTS)
+ m->opt_flags = OPT_IGNORE|OPT_NOSHORT;
+ else
m->opt_action = set_ptn_size;
}
@@ -371,6 +457,10 @@ fill_ptn_menu(struct partition_usage_set
m->opt_action = add_other_ptn_size;
m++;
+ m->opt_name = MSG_clone_from_elsewhere;
+ m->opt_action = inst_ext_clone;
+ m++;
+
m->opt_name = MSG_askunits;
m->opt_menu = MENU_sizechoice;
m->opt_flags = OPT_SUB;
@@ -552,7 +642,7 @@ get_ptn_sizes(struct partition_usage_set
wrefresh(stdscr);
if (pset->menu_opts == NULL)
- pset->menu_opts = calloc(pset->num+3, sizeof(*pset->menu_opts));
+ pset->menu_opts = calloc(pset->num+4, sizeof(*pset->menu_opts));
pset->menu = -1;
num = fill_ptn_menu(pset);
@@ -1000,7 +1090,7 @@ sort_and_sync_parts(struct partition_usa
continue;
if (pset->infos[i].flags & PUIFLG_JUST_MOUNTPOINT)
continue;
- if ((pset->infos[i].flags & (PUIFLG_IS_OUTER|PUIFLAG_ADD_INNER))
+ if ((pset->infos[i].flags & (PUIFLG_IS_OUTER|PUIFLG_ADD_INNER))
== PUIFLG_IS_OUTER)
continue;
if (pno >= pset->parts->num_part)
@@ -1046,17 +1136,73 @@ sort_and_sync_parts(struct partition_usa
pset->infos = infos;
}
+/*
+ * Convert clone entries with more than one source into
+ * several entries with a single source each.
+ */
+static void
+normalize_clones(struct part_usage_info **infos, size_t *num)
+{
+ size_t i, j, add_clones;
+ struct part_usage_info *ui, *src, *target;
+ struct disk_part_info info;
+ struct selected_partition *clone;
+
+ for (add_clones = 0, i = 0; i < *num; i++) {
+ if ((*infos)[i].clone_src != NULL &&
+ (*infos)[i].flags & PUIFLG_CLONE_PARTS &&
+ (*infos)[i].cur_part_id == NO_PART)
+ add_clones += (*infos)[i].clone_src->num_sel-1;
+ }
+ if (add_clones == 0)
+ return;
+
+ ui = calloc(*num+add_clones, sizeof(**infos));
+ if (ui == NULL)
+ return; /* can not handle this well here, drop some clones */
+
+ /* walk the list and dedup clones */
+ for (src = *infos, target = ui, i = 0; i < *num; i++) {
+ if (src != target)
+ *target = *src;
+ if (target->clone_src != NULL &&
+ (target->flags & PUIFLG_CLONE_PARTS) &&
+ target->cur_part_id == NO_PART) {
+ for (j = 0; j < src->clone_src->num_sel; j++) {
+ if (j > 0) {
+ target++;
+ *target = *src;
+ }
+ target->clone_ndx = j;
+ clone = &target->clone_src->selection[j];
+ clone->parts->pscheme->get_part_info(
+ clone->parts, clone->id, &info);
+ target->size = info.size;
+ }
+ }
+ target++;
+ src++;
+ }
+ *num += add_clones;
+ assert((target-ui) >= 0 && (size_t)(target-ui) == *num);
+ free(*infos);
+ *infos = ui;
+}
+
static void
apply_settings_to_partitions(struct pm_devs *p, struct disk_partitions *parts,
struct partition_usage_set *wanted, daddr_t start, daddr_t size)
{
size_t i, exp_ndx = ~0U;
daddr_t planned_space = 0, nsp, from, align;
- struct disk_part_info *infos;
+ struct disk_part_info *infos, cinfo, srcinfo;
struct disk_part_free_space space;
struct disk_partitions *ps = NULL;
+ struct selected_partition *sp;
part_id pno, new_part_id;
+ normalize_clones(&wanted->infos, &wanted->num);
+
infos = calloc(wanted->num, sizeof(*infos));
if (infos == NULL) {
err_msg_win(err_outofmem);
@@ -1167,14 +1313,14 @@ apply_settings_to_partitions(struct pm_d
new_part_id, &infos[i]);
want->cur_part_id = new_part_id;
- want->flags |= PUIFLAG_ADD_INNER|PUIFLG_IS_OUTER;
+ want->flags |= PUIFLG_ADD_INNER|PUIFLG_IS_OUTER;
from = rounddown(infos[i].start +
infos[i].size+outer_align, outer_align);
}
}
/*
- * Now add new inner partitions
+ * Now add new inner partitions (and cloned partitions)
*/
for (i = 0; i < wanted->num && from < wanted->parts->disk_size; i++) {
struct part_usage_info *want = &wanted->infos[i];
@@ -1183,35 +1329,66 @@ apply_settings_to_partitions(struct pm_d
continue;
if (want->flags & (PUIFLG_JUST_MOUNTPOINT|PUIFLG_IS_OUTER))
continue;
- if (want->size <= 0)
- continue;
+ if ((want->flags & PUIFLG_CLONE_PARTS) &&
+ want->clone_src != NULL &&
+ want->clone_ndx < want->clone_src->num_sel) {
+ sp = &want->clone_src->selection[want->clone_ndx];
+ if (!sp->parts->pscheme->get_part_info(
+ sp->parts, sp->id, &srcinfo))
+ continue;
+ if (!wanted->parts->pscheme->
+ adapt_foreign_part_info(wanted->parts,
+ &cinfo, sp->parts->pscheme, &srcinfo))
+ continue;
- size_t cnt = wanted->parts->pscheme->get_free_spaces(
- wanted->parts, &space, 1, want->size-align, align, from,
- -1);
- if (cnt == 0)
- cnt = wanted->parts->pscheme->get_free_spaces(
- wanted->parts, &space, 1,
- want->size-5*align, align, from, -1);
-
- if (cnt == 0)
- continue; /* no free space for this partition */
-
- infos[i].start = space.start;
- infos[i].size = min(want->size, space.size);
- infos[i].nat_type =
- wanted->parts->pscheme->get_fs_part_type(want->fs_type,
- want->fs_version);
- infos[i].last_mounted = want->mount;
- infos[i].fs_type = want->fs_type;
- infos[i].fs_sub_type = want->fs_version;
- if (want->fs_type != FS_UNUSED && want->type != PT_swap) {
- want->instflags |= PUIINST_NEWFS;
- if (want->mount[0] != 0)
- want->instflags |= PUIINST_MOUNT;
+ /* find space for cinfo and add a partition */
+ size_t cnt = wanted->parts->pscheme->get_free_spaces(
+ wanted->parts, &space, 1, want->size-align, align,
+ from, -1);
+ if (cnt == 0)
+ cnt = wanted->parts->pscheme->get_free_spaces(
+ wanted->parts, &space, 1,
+ want->size-5*align, align, from, -1);
+
+ if (cnt == 0)
+ continue; /* no free space for this clone */
+
+ infos[i] = cinfo;
+ infos[i].start = space.start;
+ new_part_id = wanted->parts->pscheme->add_partition(
+ wanted->parts, &infos[i], NULL);
+ } else {
+ if (want->size <= 0)
+ continue;
+ size_t cnt = wanted->parts->pscheme->get_free_spaces(
+ wanted->parts, &space, 1, want->size-align, align,
+ from, -1);
+ if (cnt == 0)
+ cnt = wanted->parts->pscheme->get_free_spaces(
+ wanted->parts, &space, 1,
+ want->size-5*align, align, from, -1);
+
+ if (cnt == 0)
+ continue; /* no free space for this partition */
+
+ infos[i].start = space.start;
+ infos[i].size = min(want->size, space.size);
+ infos[i].nat_type =
+ wanted->parts->pscheme->get_fs_part_type(
+ want->fs_type, want->fs_version);
+ infos[i].last_mounted = want->mount;
+ infos[i].fs_type = want->fs_type;
+ infos[i].fs_sub_type = want->fs_version;
+ if (want->fs_type != FS_UNUSED &&
+ want->type != PT_swap) {
+ want->instflags |= PUIINST_NEWFS;
+ if (want->mount[0] != 0)
+ want->instflags |= PUIINST_MOUNT;
+ }
+ new_part_id = wanted->parts->pscheme->add_partition(
+ wanted->parts, &infos[i], NULL);
}
- new_part_id = wanted->parts->pscheme->add_partition(
- wanted->parts, &infos[i], NULL);
+
if (new_part_id == NO_PART)
continue; /* failed to add, skip */
@@ -1235,8 +1412,8 @@ apply_settings_to_partitions(struct pm_d
if (want->size <= 0)
continue;
- if ((want->flags & (PUIFLAG_ADD_INNER|PUIFLG_IS_OUTER)) !=
- (PUIFLAG_ADD_INNER|PUIFLG_IS_OUTER))
+ if ((want->flags & (PUIFLG_ADD_INNER|PUIFLG_IS_OUTER)) !=
+ (PUIFLG_ADD_INNER|PUIFLG_IS_OUTER))
continue;
infos[i].start = want->cur_start;
Index: src/usr.sbin/sysinst/defs.h
diff -u src/usr.sbin/sysinst/defs.h:1.45 src/usr.sbin/sysinst/defs.h:1.46
--- src/usr.sbin/sysinst/defs.h:1.45 Wed Oct 2 11:16:04 2019
+++ src/usr.sbin/sysinst/defs.h Tue Nov 12 16:33:14 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: defs.h,v 1.45 2019/10/02 11:16:04 maya Exp $ */
+/* $NetBSD: defs.h,v 1.46 2019/11/12 16:33:14 martin Exp $ */
/*
* Copyright 1997 Piermont Information Systems Inc.
@@ -252,8 +252,9 @@ struct part_usage_info {
#define PUIFLAG_ADD_OUTER 2 /* Add this partition to the outer
* partitions (if available) */
#define PUIFLG_IS_OUTER 4 /* this is an existing outer one */
-#define PUIFLAG_ADD_INNER 8 /* add outer also to inner */
+#define PUIFLG_ADD_INNER 8 /* add outer also to inner */
#define PUIFLG_JUST_MOUNTPOINT 16 /* tmpfs of mfs mountpoints */
+#define PUIFLG_CLONE_PARTS 32 /* clone external partitions */
uint flags;
struct disk_partitions *parts; /* Where does this partition live?
* We currently only support
@@ -282,6 +283,17 @@ struct part_usage_info {
unsigned int instflags; /* installer handling flags */
uint fs_type, fs_version; /* e.g. FS_LFS, or FS_BSDFS,
* version = 2 for FFSv2 */
+ /*
+ * Only != NULL when PUIFLG_CLONE_PARTS is set, describes the
+ * source partitions to clone here.
+ */
+ struct selected_partitions *clone_src;
+ /*
+ * If clone_src != NULL, this record corresponds to a single
+ * selected source partition, if clone_ndx is a valid index in clone_src
+ * (>= 0 && <= clone_src->num_sel, or all of them if clone_ndx = ~0U.
+ */
+ size_t clone_ndx;
};
/*
@@ -607,6 +619,30 @@ bool is_cdrom_device(const char *dev, bo
bool is_bootable_device(const char *dev);
bool is_partitionable_device(const char *dev);
bool convert_scheme(struct pm_devs *p, bool is_boot_drive, const char **err_msg);
+/* a single partition selected for cloning (etc) */
+struct selected_partition {
+ struct disk_partitions *parts;
+ part_id id;
+};
+struct selected_partitions {
+ struct selected_partition *selection;
+ size_t num_sel;
+ bool with_data; /* partitions and their data selected */
+ bool free_parts; /* caller should free parts */
+};
+bool select_partitions(struct selected_partitions *res,
+ const struct disk_partitions *ignore);
+daddr_t selected_parts_size(struct selected_partitions *);
+void free_selected_partitions(struct selected_partitions *);
+
+struct clone_target_menu_data {
+ struct partition_usage_set usage;
+ int res;
+};
+
+int clone_target_select(menudesc *m, void *arg);
+bool clone_partition_data(struct disk_partitions *dest_parts, part_id did,
+ struct disk_partitions *src_parts, part_id sid);
struct menudesc;
void disp_cur_fspart(int, int);
@@ -716,6 +752,7 @@ bool md_parts_use_wholedisk(struct disk_
/* from util.c */
bool root_is_read_only(void);
void get_ptn_alignment(const struct disk_partitions *parts, daddr_t *align, daddr_t *p0off);
+struct disk_partitions *get_inner_parts(struct disk_partitions *parts);
char* str_arg_subst(const char *, size_t, const char **);
void msg_display_subst(const char *, size_t, ...);
void msg_display_add_subst(const char *, size_t, ...);
Index: src/usr.sbin/sysinst/disklabel.c
diff -u src/usr.sbin/sysinst/disklabel.c:1.14 src/usr.sbin/sysinst/disklabel.c:1.15
--- src/usr.sbin/sysinst/disklabel.c:1.14 Mon Oct 21 16:09:59 2019
+++ src/usr.sbin/sysinst/disklabel.c Tue Nov 12 16:33:14 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: disklabel.c,v 1.14 2019/10/21 16:09:59 martin Exp $ */
+/* $NetBSD: disklabel.c,v 1.15 2019/11/12 16:33:14 martin Exp $ */
/*
* Copyright 2018 The NetBSD Foundation, Inc.
@@ -140,7 +140,7 @@ disklabel_parts_new(const char *dev, dad
parts->l.d_secpercyl = geo.dg_nsectors * geo.dg_ntracks;
parts->dp.pscheme = &disklabel_parts;
- parts->dp.disk = dev;
+ parts->dp.disk = strdup(dev);
parts->dp.disk_start = start;
parts->dp.disk_size = parts->dp.free_space = len;
disklabel_init_default_alignment(parts, parts->l.d_secpercyl);
@@ -216,7 +216,7 @@ disklabel_parts_read(const char *disk, d
if (len > disklabel_parts.size_limit)
len = disklabel_parts.size_limit;
parts->dp.pscheme = scheme;
- parts->dp.disk = disk;
+ parts->dp.disk = strdup(disk);
parts->dp.disk_start = start;
parts->dp.disk_size = parts->dp.free_space = len;
disklabel_init_default_alignment(parts, 0);
@@ -582,6 +582,12 @@ disklabel_get_fs_part_type(unsigned fsty
}
static const struct part_type_desc *
+disklabel_create_unknown_part_type(void)
+{
+ return disklabel_find_type(FS_OTHER, false);
+}
+
+static const struct part_type_desc *
disklabel_get_generic_type(enum part_type pt)
{
size_t nt;
@@ -1076,6 +1082,7 @@ disklabel_free(struct disk_partitions *a
{
assert(arg != NULL);
+ free(__UNCONST(arg->disk));
free(arg);
}
@@ -1100,7 +1107,9 @@ disklabel_parts = {
.get_generic_part_type = disklabel_get_generic_type,
.get_fs_part_type = disklabel_get_fs_part_type,
.create_custom_part_type = disklabel_create_custom_part_type,
+ .create_unknown_part_type = disklabel_create_unknown_part_type,
.get_part_alignment = disklabel_get_alignment,
+ .adapt_foreign_part_info = generic_adapt_foreign_part_info,
.get_part_info = disklabel_get_part_info,
.can_add_partition = disklabel_can_add_partition,
.set_part_info = disklabel_set_part_info,
Index: src/usr.sbin/sysinst/disks.c
diff -u src/usr.sbin/sysinst/disks.c:1.54 src/usr.sbin/sysinst/disks.c:1.55
--- src/usr.sbin/sysinst/disks.c:1.54 Fri Oct 25 12:49:58 2019
+++ src/usr.sbin/sysinst/disks.c Tue Nov 12 16:33:14 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: disks.c,v 1.54 2019/10/25 12:49:58 martin Exp $ */
+/* $NetBSD: disks.c,v 1.55 2019/11/12 16:33:14 martin Exp $ */
/*
* Copyright 1997 Piermont Information Systems Inc.
@@ -734,7 +734,7 @@ convert_copy(struct disk_partitions *old
}
if (!new_parts->pscheme->adapt_foreign_part_info(new_parts,
- &oinfo, &ninfo))
+ &ninfo, old_parts->pscheme, &oinfo))
continue;
new_parts->pscheme->add_partition(new_parts, &ninfo, NULL);
}
@@ -2045,3 +2045,472 @@ get_dkwedges(struct dkwedge_info **dkw,
return dkwl.dkwl_nwedges;
}
+
+/*
+ * Helper structures used in the partition select menu
+ */
+struct single_partition {
+ struct disk_partitions *parts;
+ part_id id;
+};
+
+struct sel_menu_data {
+ struct single_partition *partitions;
+ struct selected_partition result;
+};
+
+static int
+select_single_part(menudesc *m, void *arg)
+{
+ struct sel_menu_data *data = arg;
+
+ data->result.parts = data->partitions[m->cursel].parts;
+ data->result.id = data->partitions[m->cursel].id;
+
+ return 1;
+}
+
+static void
+display_single_part(menudesc *m, int opt, void *arg)
+{
+ const struct sel_menu_data *data = arg;
+ struct disk_part_info info;
+ struct disk_partitions *parts = data->partitions[opt].parts;
+ part_id id = data->partitions[opt].id;
+ int l;
+ const char *desc = NULL;
+ char line[MENUSTRSIZE*2];
+
+ if (!parts->pscheme->get_part_info(parts, id, &info))
+ return;
+
+ if (parts->pscheme->other_partition_identifier != NULL)
+ desc = parts->pscheme->other_partition_identifier(
+ parts, id);
+
+ daddr_t start = info.start / sizemult;
+ daddr_t size = info.size / sizemult;
+ snprintf(line, sizeof line, "%s [%" PRIu64 " @ %" PRIu64 "]",
+ parts->disk, size, start);
+
+ if (info.nat_type != NULL) {
+ strlcat(line, " ", sizeof line);
+ strlcat(line, info.nat_type->description, sizeof line);
+ }
+
+ if (desc != NULL) {
+ strlcat(line, ": ", sizeof line);
+ strlcat(line, desc, sizeof line);
+ }
+
+ l = strlen(line);
+ if (l >= (m->w))
+ strcpy(line + (m->w-3), "...");
+ wprintw(m->mw, "%s", line);
+}
+
+/*
+ * is the given "test" partitions set used in the selected set?
+ */
+static bool
+selection_has_parts(struct selected_partitions *sel,
+ const struct disk_partitions *test)
+{
+ size_t i;
+
+ for (i = 0; i < sel->num_sel; i++) {
+ if (sel->selection[i].parts == test)
+ return true;
+ }
+ return false;
+}
+
+/*
+ * is the given "test" partition in the selected set?
+ */
+static bool
+selection_has_partition(struct selected_partitions *sel,
+ const struct disk_partitions *test, part_id test_id)
+{
+ size_t i;
+
+ for (i = 0; i < sel->num_sel; i++) {
+ if (sel->selection[i].parts == test &&
+ sel->selection[i].id == test_id)
+ return true;
+ }
+ return false;
+}
+
+/*
+ * let the user select a partition, optionally skipping all partitions
+ * on the "ignore" device
+ */
+static bool
+add_select_partition(struct selected_partitions *res,
+ struct disk_partitions **all_parts, size_t all_cnt)
+{
+ struct disk_partitions *ps;
+ struct disk_part_info info;
+ part_id id;
+ struct single_partition *partitions, *pp;
+ struct menu_ent *part_menu_opts, *menup;
+ size_t n, part_cnt;
+ int sel_menu;
+
+ /*
+ * count how many items our menu will have
+ */
+ part_cnt = 0;
+ for (n = 0; n < all_cnt; n++) {
+ ps = all_parts[n];
+ for (id = 0; id < ps->num_part; id++) {
+ if (selection_has_partition(res, ps, id))
+ continue;
+ if (!ps->pscheme->get_part_info(ps, id, &info))
+ continue;
+ if (info.flags & (PTI_SEC_CONTAINER|PTI_WHOLE_DISK|
+ PTI_PSCHEME_INTERNAL|PTI_RAW_PART))
+ continue;
+ part_cnt++;
+ }
+ }
+
+ /*
+ * create a menu from this and let the user
+ * select one partition
+ */
+ part_menu_opts = NULL;
+ partitions = calloc(part_cnt, sizeof *partitions);
+ if (partitions == NULL)
+ goto done;
+ part_menu_opts = calloc(part_cnt, sizeof *part_menu_opts);
+ if (part_menu_opts == NULL)
+ goto done;
+ pp = partitions;
+ menup = part_menu_opts;
+ for (n = 0; n < all_cnt; n++) {
+ ps = all_parts[n];
+ for (id = 0; id < ps->num_part; id++) {
+ if (selection_has_partition(res, ps, id))
+ continue;
+ if (!ps->pscheme->get_part_info(ps, id, &info))
+ continue;
+ if (info.flags & (PTI_SEC_CONTAINER|PTI_WHOLE_DISK|
+ PTI_PSCHEME_INTERNAL|PTI_RAW_PART))
+ continue;
+ pp->parts = ps;
+ pp->id = id;
+ pp++;
+ menup->opt_action = select_single_part;
+ menup++;
+ }
+ }
+ sel_menu = new_menu(MSG_select_foreign_part, part_menu_opts, part_cnt,
+ 3, 3, 0, 60,
+ MC_SUBMENU | MC_SCROLL | MC_NOCLEAR,
+ NULL, display_single_part, NULL,
+ NULL, NULL);
+ if (sel_menu != -1) {
+ struct selected_partition *newsels;
+ struct sel_menu_data data;
+
+ memset(&data, 0, sizeof data);
+ data.partitions = partitions;
+ process_menu(sel_menu, &data);
+ free_menu(sel_menu);
+
+ if (data.result.parts != NULL) {
+ newsels = realloc(res->selection,
+ sizeof(*res->selection)*(res->num_sel+1));
+ if (newsels != NULL) {
+ res->selection = newsels;
+ newsels += res->num_sel++;
+ newsels->parts = data.result.parts;
+ newsels->id = data.result.id;
+ }
+ }
+ }
+
+ /*
+ * Final cleanup
+ */
+done:
+ free(part_menu_opts);
+ free(partitions);
+
+ return res->num_sel > 0;
+}
+
+struct part_selection_and_all_parts {
+ struct selected_partitions *selection;
+ struct disk_partitions **all_parts;
+ size_t all_cnt;
+ char *title;
+ bool cancelled;
+};
+
+static int
+toggle_clone_data(struct menudesc *m, void *arg)
+{
+ struct part_selection_and_all_parts *sel = arg;
+
+ sel->selection->with_data = !sel->selection->with_data;
+ return 0;
+}
+
+static int
+add_another(struct menudesc *m, void *arg)
+{
+ struct part_selection_and_all_parts *sel = arg;
+
+ add_select_partition(sel->selection, sel->all_parts, sel->all_cnt);
+ return 0;
+}
+
+static int
+cancel_clone(struct menudesc *m, void *arg)
+{
+ struct part_selection_and_all_parts *sel = arg;
+
+ sel->cancelled = true;
+ return 1;
+}
+
+static void
+update_sel_part_title(struct part_selection_and_all_parts *sel)
+{
+ struct disk_part_info info;
+ char *buf, line[MENUSTRSIZE];
+ size_t buf_len, i;
+
+ buf_len = MENUSTRSIZE * (1+sel->selection->num_sel);
+ buf = malloc(buf_len);
+ if (buf == NULL)
+ return;
+
+ strcpy(buf, msg_string(MSG_select_source_hdr));
+ for (i = 0; i < sel->selection->num_sel; i++) {
+ struct selected_partition *s =
+ &sel->selection->selection[i];
+ if (!s->parts->pscheme->get_part_info(s->parts, s->id, &info))
+ continue;
+ daddr_t start = info.start / sizemult;
+ daddr_t size = info.size / sizemult;
+ sprintf(line, "\n %s [%" PRIu64 " @ %" PRIu64 "] ",
+ s->parts->disk, size, start);
+ if (info.nat_type != NULL)
+ strlcat(line, info.nat_type->description, sizeof(line));
+ strlcat(buf, line, buf_len);
+ }
+ free(sel->title);
+ sel->title = buf;
+}
+
+static void
+post_sel_part(struct menudesc *m, void *arg)
+{
+ struct part_selection_and_all_parts *sel = arg;
+
+ if (m->mw == NULL)
+ return;
+ update_sel_part_title(sel);
+ m->title = sel->title;
+ m->h = 0;
+ resize_menu_height(m);
+}
+
+static void
+fmt_sel_part_line(struct menudesc *m, int i, void *arg)
+{
+ struct part_selection_and_all_parts *sel = arg;
+
+ wprintw(m->mw, "%s: %s", msg_string(MSG_clone_with_data),
+ sel->selection->with_data ?
+ msg_string(MSG_Yes) :
+ msg_string(MSG_No));
+}
+
+bool
+select_partitions(struct selected_partitions *res,
+ const struct disk_partitions *ignore)
+{
+ struct disk_desc disks[MAX_DISKS];
+ struct disk_partitions *ps;
+ struct part_selection_and_all_parts data;
+ struct pm_devs *i;
+ size_t j;
+ int cnt, n, m;
+ static menu_ent men[] = {
+ { .opt_name = MSG_select_source_add,
+ .opt_action = add_another },
+ { .opt_action = toggle_clone_data },
+ { .opt_name = MSG_cancel, .opt_action = cancel_clone },
+ };
+
+ memset(res, 0, sizeof *res);
+ memset(&data, 0, sizeof data);
+ data.selection = res;
+
+ /*
+ * collect all available partition sets
+ */
+ data.all_cnt = 0;
+ if (SLIST_EMPTY(&pm_head)) {
+ cnt = get_disks(disks, false);
+ if (cnt <= 0)
+ return false;
+
+ /*
+ * allocate two slots for each disk (primary/secondary)
+ */
+ data.all_parts = calloc(2*cnt, sizeof *data.all_parts);
+ if (data.all_parts == NULL)
+ return false;
+
+ for (n = 0; n < cnt; n++) {
+ if (ignore != NULL &&
+ strcmp(disks[n].dd_name, ignore->disk) == 0)
+ continue;
+
+ ps = partitions_read_disk(disks[n].dd_name,
+ disks[n].dd_totsec, disks[n].dd_no_mbr);
+ if (ps == NULL)
+ continue;
+ data.all_parts[data.all_cnt++] = ps;
+ ps = get_inner_parts(ps);
+ if (ps == NULL)
+ continue;
+ data.all_parts[data.all_cnt++] = ps;
+ }
+ if (data.all_cnt > 0)
+ res->free_parts = true;
+ } else {
+ cnt = 0;
+ SLIST_FOREACH(i, &pm_head, l)
+ cnt++;
+
+ data.all_parts = calloc(cnt, sizeof *data.all_parts);
+ if (data.all_parts == NULL)
+ return false;
+
+ SLIST_FOREACH(i, &pm_head, l) {
+ if (i->parts == NULL)
+ continue;
+ if (i->parts == ignore)
+ continue;
+ data.all_parts[data.all_cnt++] = i->parts;
+ }
+ }
+
+ if (!add_select_partition(res, data.all_parts, data.all_cnt))
+ goto fail;
+
+ /* loop with menu */
+ update_sel_part_title(&data);
+ m = new_menu(data.title, men, __arraycount(men), 3, 2, 0, 65, MC_SCROLL,
+ post_sel_part, fmt_sel_part_line, NULL, NULL,
+ "Source selection OK, proceed to target selection");
+ process_menu(m, &data);
+ free(data.title);
+ if (res->num_sel == 0)
+ goto fail;
+
+ /* cleanup */
+ if (res->free_parts) {
+ for (j = 0; j < data.all_cnt; j++) {
+ if (selection_has_parts(res, data.all_parts[j]))
+ continue;
+ if (data.all_parts[j]->parent != NULL)
+ continue;
+ data.all_parts[j]->pscheme->free(data.all_parts[j]);
+ }
+ }
+ free(data.all_parts);
+ return true;
+
+fail:
+ if (res->free_parts) {
+ for (j = 0; j < data.all_cnt; j++) {
+ if (data.all_parts[j]->parent != NULL)
+ continue;
+ data.all_parts[j]->pscheme->free(data.all_parts[j]);
+ }
+ }
+ free(data.all_parts);
+ return false;
+}
+
+void
+free_selected_partitions(struct selected_partitions *selected)
+{
+ size_t i;
+ struct disk_partitions *parts;
+
+ if (!selected->free_parts)
+ return;
+
+ for (i = 0; i < selected->num_sel; i++) {
+ parts = selected->selection[i].parts;
+
+ /* remove from list before testing for other instances */
+ selected->selection[i].parts = NULL;
+
+ /* if this is the secondary partion set, the parent owns it */
+ if (parts->parent != NULL)
+ continue;
+
+ /* only free once (we use the last one) */
+ if (selection_has_parts(selected, parts))
+ continue;
+ parts->pscheme->free(parts);
+ }
+ free(selected->selection);
+}
+
+daddr_t
+selected_parts_size(struct selected_partitions *selected)
+{
+ struct disk_part_info info;
+ size_t i;
+ daddr_t s = 0;
+
+ for (i = 0; i < selected->num_sel; i++) {
+ if (!selected->selection[i].parts->pscheme->get_part_info(
+ selected->selection[i].parts,
+ selected->selection[i].id, &info))
+ continue;
+ s += info.size;
+ }
+
+ return s;
+}
+
+int
+clone_target_select(menudesc *m, void *arg)
+{
+ struct clone_target_menu_data *data = arg;
+
+ data->res = m->cursel;
+ return 1;
+}
+
+bool
+clone_partition_data(struct disk_partitions *dest_parts, part_id did,
+ struct disk_partitions *src_parts, part_id sid)
+{
+ char src_dev[MAXPATHLEN], target_dev[MAXPATHLEN];
+
+ if (!src_parts->pscheme->get_part_device(
+ src_parts, sid, src_dev, sizeof src_dev, NULL,
+ raw_dev_name, true))
+ return false;
+ if (!dest_parts->pscheme->get_part_device(
+ dest_parts, did, target_dev, sizeof target_dev, NULL,
+ raw_dev_name, true))
+ return false;
+
+ return run_program(RUN_DISPLAY | RUN_PROGRESS,
+ "progress -f %s -b 1m dd bs=1m of=%s",
+ src_dev, target_dev) == 0;
+}
Index: src/usr.sbin/sysinst/gpt.c
diff -u src/usr.sbin/sysinst/gpt.c:1.11 src/usr.sbin/sysinst/gpt.c:1.12
--- src/usr.sbin/sysinst/gpt.c:1.11 Mon Aug 26 12:14:06 2019
+++ src/usr.sbin/sysinst/gpt.c Tue Nov 12 16:33:14 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: gpt.c,v 1.11 2019/08/26 12:14:06 martin Exp $ */
+/* $NetBSD: gpt.c,v 1.12 2019/11/12 16:33:14 martin Exp $ */
/*
* Copyright 2018 The NetBSD Foundation, Inc.
@@ -32,10 +32,12 @@
#include "md.h"
#include "gpt_uuid.h"
#include <assert.h>
+#include <err.h>
#include <paths.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <util.h>
+#include <uuid.h>
bool gpt_parts_check(void); /* check for needed binaries */
@@ -44,7 +46,8 @@ bool gpt_parts_check(void); /* check for
/* a GPT based disk_partitions interface */
#define GUID_STR_LEN 40
-#define GPT_PTYPE_MAX 32 /* should be > gpt type -l | wc -l */
+#define GPT_PTYPE_ALLOC 32 /* initial type array allocation, should be >
+ * gpt type -l | wc -l */
#define GPT_DEV_LEN 16 /* dkNN */
#define GPT_PARTS_PER_SEC 4 /* a 512 byte sector hols 4 entries */
@@ -112,8 +115,11 @@ struct {
{ .name = "vmresered", .fstype = FS_VMWRESV, .ptype = PT_unknown }
};
-static size_t gpt_ptype_cnt;
-static struct gpt_ptype_desc gpt_ptype_descs[GPT_PTYPE_MAX];
+static size_t gpt_ptype_cnt = 0, gpt_ptype_alloc = 0;
+static struct gpt_ptype_desc *gpt_ptype_descs = NULL;
+
+/* "well" known types with special handling */
+static const struct part_type_desc *gpt_native_root;
/* similar to struct gpt_ent, but matching our needs */
struct gpt_part_entry {
@@ -364,7 +370,7 @@ gpt_read_from_disk(const char *dev, dadd
}
parts->dp.pscheme = scheme;
- parts->dp.disk = dev;
+ parts->dp.disk = strdup(dev);
parts->dp.disk_start = start;
parts->dp.disk_size = disk_size;
parts->dp.free_space = avail_size;
@@ -449,7 +455,7 @@ gpt_create_new(const char *disk, daddr_t
return NULL;
parts->dp.pscheme = &gpt_parts;
- parts->dp.disk = disk;
+ parts->dp.disk = strdup(disk);
gpt_md_init(is_boot_drive, &parts->max_num_parts, &parts->prologue,
&parts->epilogue);
@@ -709,26 +715,6 @@ gpt_get_free_spaces(const struct disk_pa
max_num_result, min_space_size, align, start, ignore);
}
-
-static bool
-gpt_adapt(const struct disk_partitions *arg,
- const struct disk_part_info *src, struct disk_part_info *dest)
-{
- /* slightly simplistic, enhance when needed */
- memcpy(dest, src, sizeof(*dest));
-
- if (src->nat_type == NULL)
- return false;
-
- dest->nat_type = arg->pscheme->get_generic_part_type(
- src->nat_type->generic_ptype);
- if (dest->nat_type == NULL)
- dest->nat_type = arg->pscheme->get_generic_part_type(
- PT_unknown);
-
- return true;
-}
-
static void
gpt_match_ptype(const char *name, struct gpt_ptype_desc *t)
{
@@ -739,6 +725,11 @@ gpt_match_ptype(const char *name, struct
t->gent.generic_ptype = gpt_fs_types[i].ptype;
t->fsflags = gpt_fs_types[i].fsflags;
t->default_fs_type = gpt_fs_types[i].fstype;
+
+ /* recongnize special entries */
+ if (gpt_native_root == NULL && i == 0)
+ gpt_native_root = &t->gent;
+
return;
}
}
@@ -751,10 +742,20 @@ gpt_match_ptype(const char *name, struct
static void
gpt_internal_add_ptype(const char *uid, const char *name, const char *desc)
{
+ if (gpt_ptype_cnt >= gpt_ptype_alloc) {
+ gpt_ptype_alloc = gpt_ptype_alloc ? 2*gpt_ptype_alloc
+ : GPT_PTYPE_ALLOC;
+ struct gpt_ptype_desc *nptypes = realloc(gpt_ptype_descs,
+ gpt_ptype_alloc*sizeof(*gpt_ptype_descs));
+ if (nptypes == 0)
+ errx(EXIT_FAILURE, "out of memory");
+ gpt_ptype_descs = nptypes;
+ }
+
strlcpy(gpt_ptype_descs[gpt_ptype_cnt].tid, uid,
sizeof(gpt_ptype_descs[gpt_ptype_cnt].tid));
- gpt_ptype_descs[gpt_ptype_cnt].gent.short_desc = name;
- gpt_ptype_descs[gpt_ptype_cnt].gent.description = desc;
+ gpt_ptype_descs[gpt_ptype_cnt].gent.short_desc = strdup(name);
+ gpt_ptype_descs[gpt_ptype_cnt].gent.description = strdup(desc);
gpt_match_ptype(name, &gpt_ptype_descs[gpt_ptype_cnt]);
gpt_ptype_cnt++;
}
@@ -766,6 +767,19 @@ gpt_init_ptypes(void)
gpt_uuid_query(gpt_internal_add_ptype);
}
+static void
+gpt_cleanup(void)
+{
+ /* free all of gpt_ptype_descs */
+ for (size_t i = 0; i < gpt_ptype_cnt; i++) {
+ free(__UNCONST(gpt_ptype_descs[i].gent.short_desc));
+ free(__UNCONST(gpt_ptype_descs[i].gent.description));
+ }
+ free(gpt_ptype_descs);
+ gpt_ptype_descs = NULL;
+ gpt_ptype_cnt = gpt_ptype_alloc = 0;
+}
+
static size_t
gpt_type_count(void)
{
@@ -793,6 +807,11 @@ gpt_get_generic_type(enum part_type gent
if (gpt_ptype_cnt == 0)
gpt_init_ptypes();
+ if (gent == PT_root)
+ return gpt_native_root;
+ if (gent == PT_unknown)
+ return NULL;
+
for (size_t i = 0; i < gpt_ptype_cnt; i++)
if (gpt_ptype_descs[i].gent.generic_ptype == gent)
return &gpt_ptype_descs[i].gent;
@@ -863,7 +882,61 @@ gpt_get_fs_part_type(unsigned fstype, un
if (fstype == gpt_fs_types[i].fstype)
return gpt_find_type(gpt_fs_types[i].name);
- return gpt_get_generic_type(PT_root);
+ return NULL;
+}
+
+static const struct part_type_desc *
+gpt_get_uuid_part_type(const uuid_t *id)
+{
+ char str[GUID_STR_LEN], desc[GUID_STR_LEN + MENUSTRSIZE];
+ const struct gpt_ptype_desc *t;
+ char *guid = NULL;
+ uint32_t err;
+
+ uuid_to_string(id, &guid, &err);
+ strlcpy(str, err == uuid_s_ok ? guid : "-", sizeof str);
+ free(guid);
+
+ t = gpt_find_guid_type(str);
+ if (t == NULL) {
+ snprintf(desc, sizeof desc, "%s (%s)",
+ msg_string(MSG_custom_type), str);
+ gpt_internal_add_ptype(str, str, desc);
+ t = gpt_find_guid_type(str);
+ assert(t != NULL);
+ }
+ return &t->gent;
+}
+
+static const struct part_type_desc *
+gpt_create_custom_part_type(const char *custom, const char **err_msg)
+{
+ uuid_t id;
+ uint32_t err;
+
+ uuid_from_string(custom, &id, &err);
+ if (err_msg != NULL &&
+ (err == uuid_s_invalid_string_uuid || err == uuid_s_bad_version)) {
+ *err_msg = MSG_invalid_guid;
+ return NULL;
+ }
+ if (err != uuid_s_ok)
+ return NULL;
+
+ return gpt_get_uuid_part_type(&id);
+}
+
+static const struct part_type_desc *
+gpt_create_unknown_part_type(void)
+{
+ uuid_t id;
+ uint32_t err;
+
+ uuid_create(&id, &err);
+ if (err != uuid_s_ok)
+ return NULL;
+
+ return gpt_get_uuid_part_type(&id);
}
static daddr_t
@@ -1312,9 +1385,11 @@ gpt_write_to_disk(struct disk_partitions
close(fd);
/*
- * Collect first root and efi partition (if available)
+ * Collect first root and efi partition (if available), clear
+ * "have wedge" flags.
*/
for (pno = 0, p = parts->partitions; p != NULL; p = p->gp_next, pno++) {
+ p->gp_flags &= ~GPEF_WEDGE;
if (root_id == NO_PART && p->gp_type != NULL) {
if (p->gp_type->gent.generic_ptype == PT_root &&
p->gp_start == pm->ptstart) {
@@ -1455,6 +1530,7 @@ gpt_free(struct disk_partitions *arg)
n = p->gp_next;
free(p);
}
+ free(__UNCONST(parts->dp.disk));
free(parts);
}
@@ -1657,6 +1733,8 @@ gpt_parts = {
.get_part_type = gpt_get_ptype,
.get_generic_part_type = gpt_get_generic_type,
.get_fs_part_type = gpt_get_fs_part_type,
+ .create_custom_part_type = gpt_create_custom_part_type,
+ .create_unknown_part_type = gpt_create_unknown_part_type,
.get_part_alignment = gpt_get_part_alignment,
.read_from_disk = gpt_read_from_disk,
.create_new_for_disk = gpt_create_new,
@@ -1671,7 +1749,7 @@ gpt_parts = {
.get_part_device = gpt_get_part_device,
.max_free_space_at = gpt_max_free_space_at,
.get_free_spaces = gpt_get_free_spaces,
- .adapt_foreign_part_info = gpt_adapt,
+ .adapt_foreign_part_info = generic_adapt_foreign_part_info,
.get_part_info = gpt_get_part_info,
.get_part_attr_str = gpt_get_part_attr_str,
.set_part_info = gpt_set_part_info,
@@ -1680,4 +1758,5 @@ gpt_parts = {
.delete_partition = gpt_delete_partition,
.write_to_disk = gpt_write_to_disk,
.free = gpt_free,
+ .cleanup = gpt_cleanup,
};
Index: src/usr.sbin/sysinst/install.c
diff -u src/usr.sbin/sysinst/install.c:1.11 src/usr.sbin/sysinst/install.c:1.12
--- src/usr.sbin/sysinst/install.c:1.11 Sat Aug 17 18:08:06 2019
+++ src/usr.sbin/sysinst/install.c Tue Nov 12 16:33:14 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: install.c,v 1.11 2019/08/17 18:08:06 martin Exp $ */
+/* $NetBSD: install.c,v 1.12 2019/11/12 16:33:14 martin Exp $ */
/*
* Copyright 1997 Piermont Information Systems Inc.
@@ -34,6 +34,7 @@
/* install.c -- system installation. */
+#include <sys/param.h>
#include <stdio.h>
#include <curses.h>
#include "defs.h"
@@ -49,6 +50,7 @@ static bool
write_all_parts(struct install_partition_desc *install)
{
struct disk_partitions **allparts, *parts;
+ struct selected_partition *src;
size_t num_parts, i, j;
bool found, res;
@@ -75,7 +77,7 @@ write_all_parts(struct install_partition
allparts[num_parts++] = parts;
}
- /* do four phases, abort anytime and go out, returning res */
+ /* do multiple phases, abort anytime and go out, returning res */
res = true;
@@ -98,7 +100,20 @@ write_all_parts(struct install_partition
/* phase 3: now we may have a first chance to enable swap space */
set_swap_if_low_ram(install);
- /* phase 4: post disklabel (used for updating boot loaders) */
+ /* phase 4: copy any cloned partitions data (if requested) */
+ for (i = 0; i < install->num; i++) {
+ if ((install->infos[i].flags & PUIFLG_CLONE_PARTS) == 0
+ || install->infos[i].clone_src == NULL
+ || !install->infos[i].clone_src->with_data)
+ continue;
+ src = &install->infos[i].clone_src
+ ->selection[install->infos[i].clone_ndx];
+ clone_partition_data(install->infos[i].parts,
+ install->infos[i].cur_part_id,
+ src->parts, src->id);
+ }
+
+ /* phase 5: post disklabel (used for updating boot loaders) */
for (i = 0; i < num_parts; i++) {
if (!md_post_disklabel(install, allparts[i])) {
res = false;
@@ -217,5 +232,5 @@ do_install(void)
hit_enter_to_continue(MSG_instcomplete, NULL);
error:
- free(install.infos);
+ free_install_desc(&install);
}
Index: src/usr.sbin/sysinst/label.c
diff -u src/usr.sbin/sysinst/label.c:1.12 src/usr.sbin/sysinst/label.c:1.13
--- src/usr.sbin/sysinst/label.c:1.12 Sun Aug 4 10:29:41 2019
+++ src/usr.sbin/sysinst/label.c Tue Nov 12 16:33:14 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: label.c,v 1.12 2019/08/04 10:29:41 martin Exp $ */
+/* $NetBSD: label.c,v 1.13 2019/11/12 16:33:14 martin Exp $ */
/*
* Copyright 1997 Jonathan Stone
@@ -36,7 +36,7 @@
#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: label.c,v 1.12 2019/08/04 10:29:41 martin Exp $");
+__RCSID("$NetBSD: label.c,v 1.13 2019/11/12 16:33:14 martin Exp $");
#endif
#include <sys/types.h>
@@ -1113,11 +1113,16 @@ fmt_fspart_header(menudesc *menu, void *
{
struct partition_usage_set *pset = arg;
char total[6], free_space[6], scol[13], ecol[13], szcol[13],
- sepline[MENUSTRSIZE], *p;
+ sepline[MENUSTRSIZE], *p, desc[MENUSTRSIZE];
const char *fstype, *flags;
int i;
- bool with_inst_flag = pset->parts->parent == NULL;
+ size_t ptn;
+ bool with_clone, with_inst_flag = pset->parts->parent == NULL;
+ with_clone = false;
+ for (ptn = 0; ptn < pset->num && !with_clone; ptn++)
+ if (pset->infos[ptn].flags & PUIFLG_CLONE_PARTS)
+ with_clone = true;
humanize_number(total, sizeof total,
pset->parts->disk_size * 512,
"", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
@@ -1125,14 +1130,19 @@ fmt_fspart_header(menudesc *menu, void *
pset->cur_free_space * 512,
"", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
+ if (with_clone)
+ strlcpy(desc, msg_string(MSG_clone_flag_desc), sizeof desc);
+ else
+ desc[0] = 0;
+ if (pset->parts->pscheme->part_flag_desc)
+ strlcat(desc, msg_string(pset->parts->pscheme->part_flag_desc),
+ sizeof desc);
+
msg_display_subst(MSG_fspart, 7, pset->parts->disk,
msg_string(pset->parts->pscheme->name),
msg_string(pset->parts->pscheme->short_name),
with_inst_flag ? msg_string(MSG_ptn_instflag_desc) : "",
- pset->parts->pscheme->part_flag_desc ?
- msg_string(pset->parts->pscheme->part_flag_desc)
- : "",
- total, free_space);
+ desc, total, free_space);
snprintf(scol, sizeof scol, "%s (%s)",
msg_string(MSG_ptnheaders_start), multname);
@@ -1177,11 +1187,40 @@ fmt_fspart_row(menudesc *m, int ptn, voi
static const char *Yes;
char flag_str[MENUSTRSIZE], *fp;
unsigned inst_flags;
+ size_t clone_cnt;
bool with_inst_flag = pset->parts->parent == NULL;
if (Yes == NULL)
Yes = msg_string(MSG_Yes);
+ if ((pset->infos[ptn].flags & PUIFLG_CLONE_PARTS) &&
+ pset->infos[ptn].cur_part_id == NO_PART) {
+ psize = pset->infos[ptn].size / sizemult;
+ if (pset->infos[ptn].clone_ndx <
+ pset->infos[ptn].clone_src->num_sel)
+ clone_cnt = 1;
+ else
+ clone_cnt = pset->infos[ptn].clone_src->num_sel;
+ if (pset->infos[ptn].cur_part_id == NO_PART)
+ wprintw(m->mw, " %12" PRIu64
+ " [%zu %s]", psize, clone_cnt,
+ msg_string(MSG_clone_target_disp));
+ else {
+ poffset = pset->infos[ptn].cur_start / sizemult;
+ pend = (pset->infos[ptn].cur_start +
+ pset->infos[ptn].size) / sizemult - 1;
+ wprintw(m->mw, "%12" PRIu64 " %12" PRIu64 " %12" PRIu64
+ " [%zu %s]",
+ poffset, pend, psize, clone_cnt,
+ msg_string(MSG_clone_target_disp));
+ }
+ if (m->title == fspart_title)
+ m->opts[ptn].opt_flags |= OPT_IGNORE;
+ else
+ m->opts[ptn].opt_flags &= ~OPT_IGNORE;
+ return;
+ }
+
if (!real_partition(pset, ptn))
return;
@@ -1189,11 +1228,22 @@ fmt_fspart_row(menudesc *m, int ptn, voi
pset->infos[ptn].cur_part_id, &info))
return;
- /* enable / disable this line if it is something like RAW_PART */
- if (info.flags & (PTI_WHOLE_DISK|PTI_PSCHEME_INTERNAL|PTI_RAW_PART))
- m->opts[ptn].opt_flags |= OPT_IGNORE;
- else
- m->opts[ptn].opt_flags &= ~OPT_IGNORE;
+ /*
+ * We use this function in multiple menus, but only want it
+ * to play with enable/disable in a single one:
+ */
+ if (m->title == fspart_title) {
+ /*
+ * Enable / disable this line if it is something
+ * like RAW_PART
+ */
+ if ((info.flags &
+ (PTI_WHOLE_DISK|PTI_PSCHEME_INTERNAL|PTI_RAW_PART))
+ || (pset->infos[ptn].flags & PUIFLG_CLONE_PARTS))
+ m->opts[ptn].opt_flags |= OPT_IGNORE;
+ else
+ m->opts[ptn].opt_flags &= ~OPT_IGNORE;
+ }
poffset = info.start / sizemult;
psize = info.size / sizemult;
@@ -1223,6 +1273,8 @@ fmt_fspart_row(menudesc *m, int ptn, voi
}
if (inst_flags & PUIINST_NEWFS)
*fp++ = msg_string(MSG_newfs_flag)[0];
+ if (pset->infos[ptn].flags & PUIFLG_CLONE_PARTS)
+ *fp++ = msg_string(MSG_clone_flag)[0];
*fp = 0;
if (pset->parts->pscheme->get_part_attr_str != NULL)
pset->parts->pscheme->get_part_attr_str(pset->parts,
@@ -1245,6 +1297,153 @@ fmt_fspart_row(menudesc *m, int ptn, voi
}
static int
+part_ext_clone(menudesc *m, void *arg)
+{
+ struct selected_partitions selected, *clone_src;
+ struct clone_target_menu_data data;
+ struct partition_usage_set *pset = arg;
+ struct part_usage_info *p;
+ struct disk_part_info sinfo, cinfo;
+ struct disk_partitions *csrc;
+ struct disk_part_free_space space;
+ menu_ent *men;
+ daddr_t clone_size, free_size, offset, align;
+ int num_men, i;
+ size_t s, clone_cnt;
+ part_id cid;
+ struct clone_data {
+ struct disk_part_info info;
+ part_id new_id;
+ size_t ndx;
+ };
+ struct clone_data *clones = NULL;
+
+ if (!select_partitions(&selected, pm->parts))
+ return 0;
+
+ clone_size = selected_parts_size(&selected);
+ num_men = pset->num+1;
+ men = calloc(num_men, sizeof *men);
+ if (men == NULL)
+ return 0;
+ for (i = 0; i < num_men; i++) {
+ men[i].opt_action = clone_target_select;
+ if (i == 0)
+ free_size = pset->infos[i].cur_start;
+ else if (i > 0 && (size_t)i < pset->num)
+ free_size = pset->infos[i].cur_start -
+ pset->infos[i-1].cur_start - pset->infos[i-1].size;
+ else
+ free_size = pset->parts->free_space;
+ if (free_size < clone_size)
+ men[i].opt_flags = OPT_IGNORE;
+ }
+ men[num_men-1].opt_name = MSG_clone_target_end;
+
+ memset(&data, 0, sizeof data);
+ data.usage = *pset;
+ data.res = -1;
+
+ data.usage.menu = new_menu(MSG_clone_target_hdr,
+ men, num_men, 3, 2, 0, 65, MC_SCROLL,
+ NULL, fmt_fspart_row, NULL, NULL, MSG_cancel);
+ process_menu(data.usage.menu, &data);
+ free_menu(data.usage.menu);
+ free(men);
+
+ if (data.res < 0)
+ goto err;
+
+ /* create temporary infos for all clones that work out */
+ clone_cnt = 0;
+ clones = calloc(selected.num_sel, sizeof(*clones));
+ if (clones == NULL)
+ goto err;
+
+ clone_src = malloc(sizeof(selected));
+ if (clone_src == NULL)
+ goto err;
+ *clone_src = selected;
+
+ /* find selected offset from data.res and insert clones there */
+ align = pset->parts->pscheme->get_part_alignment(pset->parts);
+ offset = -1;
+ if (data.res > 0)
+ offset = pset->infos[data.res-1].cur_start
+ + pset->infos[data.res-1].size;
+ else
+ offset = 0;
+ for (s = 0; s < selected.num_sel; s++) {
+ csrc = selected.selection[s].parts;
+ cid = selected.selection[s].id;
+ csrc->pscheme->get_part_info(csrc, cid, &sinfo);
+ if (!pset->parts->pscheme->adapt_foreign_part_info(
+ pset->parts, &cinfo, csrc->pscheme, &sinfo))
+ continue;
+ size_t cnt = pset->parts->pscheme->get_free_spaces(
+ pset->parts, &space, 1, cinfo.size-align, align,
+ offset, -1);
+ if (cnt == 0)
+ continue;
+ cinfo.start = space.start;
+ cid = pset->parts->pscheme->add_partition(
+ pset->parts, &cinfo, NULL);
+ if (cid == NO_PART)
+ continue;
+ pset->parts->pscheme->get_part_info(pset->parts, cid, &cinfo);
+ clones[clone_cnt].info = cinfo;
+ clones[clone_cnt].new_id = cid;
+ clones[clone_cnt].ndx = s;
+ clone_cnt++;
+ offset = rounddown(cinfo.start+cinfo.size+align, align);
+ }
+
+ /* insert new clone records at offset data.res */
+ men = realloc(m->opts, (m->numopts+clone_cnt)*sizeof(*m->opts));
+ if (men == NULL)
+ goto err;
+ pset->menu_opts = men;
+ m->opts = men;
+ m->numopts += clone_cnt;
+
+ p = realloc(pset->infos, (pset->num+clone_cnt)*sizeof(*pset->infos));
+ if (p == NULL)
+ goto err;
+ pset->infos = p;
+
+ men += data.res;
+ p += data.res;
+ memmove(men+clone_cnt, men,
+ sizeof(*men)*(m->numopts-data.res-clone_cnt));
+ if (pset->num > (size_t)data.res)
+ memmove(p+clone_cnt, p, sizeof(*p)*(pset->num-data.res));
+ memset(men, 0, sizeof(*men)*clone_cnt);
+ memset(p, 0, sizeof(*p)*clone_cnt);
+ for (s = 0; s < clone_cnt; s++) {
+ p[s].cur_part_id = clones[s].new_id;
+ p[s].cur_start = clones[s].info.start;
+ p[s].size = clones[s].info.size;
+ p[s].cur_flags = clones[s].info.flags;
+ p[s].flags = PUIFLG_CLONE_PARTS;
+ p[s].parts = pset->parts;
+ p[s].clone_src = clone_src;
+ p[s].clone_ndx = s;
+ }
+ free(clones);
+ m->cursel = ((size_t)data.res >= pset->num) ? 0 : data.res+clone_cnt;
+ pset->num += clone_cnt;
+ m->h = 0;
+ resize_menu_height(m);
+
+ return -1;
+
+err:
+ free(clones);
+ free_selected_partitions(&selected);
+ return 0;
+}
+
+static int
edit_fspart_pack(menudesc *m, void *arg)
{
struct partition_usage_set *pset = arg;
@@ -1396,7 +1595,7 @@ edit_and_check_label(struct pm_devs *p,
pset->parts->pscheme->set_disk_pack_name != NULL;
pset->menu_opts = calloc(pset->parts->num_part
- +3+may_add+may_edit_pack,
+ +4+may_add+may_edit_pack,
sizeof *pset->menu_opts);
if (pset->menu_opts == NULL)
return 0;
@@ -1432,6 +1631,11 @@ edit_and_check_label(struct pm_devs *p,
op->opt_action = edit_fspart_pack;
op++;
}
+
+ /* add a clone-from-elsewhere option */
+ op->opt_name = MSG_clone_from_elsewhere;
+ op->opt_action = part_ext_clone;
+ op++;
/* and abort option */
op->opt_name = MSG_cancel;
@@ -1439,7 +1643,7 @@ edit_and_check_label(struct pm_devs *p,
op->opt_action = edit_fspart_abort;
op++;
cnt = op - pset->menu_opts;
- assert(cnt == pset->parts->num_part+3+may_add+may_edit_pack);
+ assert(cnt == pset->parts->num_part+4+may_add+may_edit_pack);
pset->menu = new_menu(fspart_title, pset->menu_opts, cnt,
0, -1, 0, 74,
Index: src/usr.sbin/sysinst/main.c
diff -u src/usr.sbin/sysinst/main.c:1.17 src/usr.sbin/sysinst/main.c:1.18
--- src/usr.sbin/sysinst/main.c:1.17 Sat Jun 22 20:46:07 2019
+++ src/usr.sbin/sysinst/main.c Tue Nov 12 16:33:14 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: main.c,v 1.17 2019/06/22 20:46:07 christos Exp $ */
+/* $NetBSD: main.c,v 1.18 2019/11/12 16:33:14 martin Exp $ */
/*
* Copyright 1997 Piermont Information Systems Inc.
@@ -281,6 +281,8 @@ main(int argc, char **argv)
pm_destroy_all();
#endif
+ partitions_cleanup();
+
exit_cleanly = 1;
return 0;
}
Index: src/usr.sbin/sysinst/msg.mi.es
diff -u src/usr.sbin/sysinst/msg.mi.es:1.17 src/usr.sbin/sysinst/msg.mi.es:1.18
--- src/usr.sbin/sysinst/msg.mi.es:1.17 Wed Oct 2 11:16:04 2019
+++ src/usr.sbin/sysinst/msg.mi.es Tue Nov 12 16:33:14 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: msg.mi.es,v 1.17 2019/10/02 11:16:04 maya Exp $ */
+/* $NetBSD: msg.mi.es,v 1.18 2019/11/12 16:33:14 martin Exp $ */
/*
* Copyright 1997 Piermont Information Systems Inc.
@@ -1284,6 +1284,7 @@ message dl_type_invalid {Invalid file sy
message cancel {Cancel}
message out_of_range {Invalid value}
+message invalid_guid {Invalid GUID}
message reedit_partitions {Re-edit}
message abort_installation {Abort installation}
@@ -1446,6 +1447,9 @@ message newfs_flag {N}
message ptn_install {instalar}
message ptn_instflag_desc {(I)nstalar, }
+message clone_flag {C}
+message clone_flag_desc {, (C)lone}
+
message parttype_gpt {Guid Partition Table (GPT)}
message parttype_gpt_short {GPT}
@@ -1471,3 +1475,15 @@ message size_ptn_not_mounted {(Other: $
message running_system {current system}
+message clone_from_elsewhere {Clone external partition(s)}
+message select_foreign_part
+{Please select an external source partition:}
+message select_source_hdr
+{Your currently selected source partitions are:}
+message clone_with_data {Clone with data}
+message select_source_add {Add another partition}
+message clone_target_end {Add at end}
+message clone_target_hdr
+{Insert cloned partitions before:}
+message clone_target_disp {cloned partition(s)}
+
Index: src/usr.sbin/sysinst/mbr.c
diff -u src/usr.sbin/sysinst/mbr.c:1.21 src/usr.sbin/sysinst/mbr.c:1.22
--- src/usr.sbin/sysinst/mbr.c:1.21 Tue Aug 27 17:23:24 2019
+++ src/usr.sbin/sysinst/mbr.c Tue Nov 12 16:33:14 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: mbr.c,v 1.21 2019/08/27 17:23:24 martin Exp $ */
+/* $NetBSD: mbr.c,v 1.22 2019/11/12 16:33:14 martin Exp $ */
/*
* Copyright 1997 Piermont Information Systems Inc.
@@ -74,6 +74,8 @@
#include <unistd.h>
#include <fcntl.h>
#include <util.h>
+#include <paths.h>
+#include <sys/ioctl.h>
#include "defs.h"
#include "mbr.h"
#include "md.h"
@@ -89,6 +91,9 @@
#define MAXSECTOR 63
+#define MBR_UNKNOWN_PTYPE 94 /* arbitrary not widely used value */
+
+
/* A list of predefined partition types */
const struct {
unsigned int ptype;
@@ -588,7 +593,7 @@ static int
write_mbr(const char *disk, mbr_info_t *mbri, int bsec, int bhead, int bcyl)
{
char diskpath[MAXPATHLEN];
- int fd, i, ret = 0;
+ int fd, i, ret = 0, bits = 0;
struct mbr_partition *mbrp;
u_int32_t pstart, psize;
#ifdef BOOTSEL
@@ -605,6 +610,10 @@ write_mbr(const char *disk, mbr_info_t *
if (fd < 0)
return -1;
+ /* Remove all wedges */
+ if (ioctl(fd, DIOCRMWEDGES, &bits) == -1)
+ return -1;
+
#ifdef BOOTSEL
/*
* If the main boot code (appears to) contain the netbsd bootcode,
@@ -646,6 +655,7 @@ write_mbr(const char *disk, mbr_info_t *
#endif
for (ext = mbri; ext != NULL; ext = ext->extended) {
+ memset(mbri->wedge, 0, sizeof mbri->wedge);
sector = ext->sector;
mbrsec = ext->mbr; /* copy sector */
mbrp = &mbrsec.mbr_parts[0];
@@ -830,7 +840,7 @@ mbr_create_new(const char *disk, daddr_t
return NULL;
parts->dp.pscheme = &mbr_parts;
- parts->dp.disk = disk;
+ parts->dp.disk = strdup(disk);
if (len > mbr_parts.size_limit)
len = mbr_parts.size_limit;
parts->dp.disk_start = start;
@@ -894,7 +904,7 @@ mbr_read_from_disk(const char *disk, dad
return NULL;
parts->dp.pscheme = scheme;
- parts->dp.disk = disk;
+ parts->dp.disk = strdup(disk);
if (len >= mbr_parts.size_limit)
len = mbr_parts.size_limit;
parts->dp.disk_start = start;
@@ -1127,6 +1137,16 @@ mbr_custom_part_type(const char *custom,
}
static const struct part_type_desc *
+mbr_create_unknown_part_type(void)
+{
+
+ if (mbr_gen_type_desc[MBR_UNKNOWN_PTYPE].gen.short_desc != NULL)
+ return &mbr_gen_type_desc[MBR_UNKNOWN_PTYPE].gen;
+
+ return mbr_new_custom_part_type(MBR_UNKNOWN_PTYPE);
+}
+
+static const struct part_type_desc *
mbr_get_gen_type_desc(unsigned int pt)
{
@@ -1231,12 +1251,80 @@ mbr_do_get_part_info(const struct disk_p
mbr_partition_to_info(mp, mb->sector, info);
if (mb->last_mounted[i] != NULL && mb->last_mounted[i][0] != 0)
info->last_mounted = mb->last_mounted[i];
- info->fs_type = mb->fs_type[i];
- info->fs_sub_type = mb->fs_sub_type[i];
+ if (mb->fs_type[i] != FS_UNUSED) {
+ info->fs_type = mb->fs_type[i];
+ info->fs_sub_type = mb->fs_sub_type[i];
+ } else {
+ info->fs_sub_type = 0;
+ switch (mp->mbrp_type) {
+ case MBR_PTYPE_FAT12:
+ case MBR_PTYPE_FAT16S:
+ case MBR_PTYPE_FAT16B:
+ case MBR_PTYPE_FAT32:
+ case MBR_PTYPE_FAT32L:
+ case MBR_PTYPE_FAT16L:
+ case MBR_PTYPE_OS2_DOS12:
+ case MBR_PTYPE_OS2_DOS16S:
+ case MBR_PTYPE_OS2_DOS16B:
+ case MBR_PTYPE_HID_FAT32:
+ case MBR_PTYPE_HID_FAT32_LBA:
+ case MBR_PTYPE_HID_FAT16_LBA:
+ case MBR_PTYPE_MDOS_FAT12:
+ case MBR_PTYPE_MDOS_FAT16S:
+ case MBR_PTYPE_MDOS_EXT:
+ case MBR_PTYPE_MDOS_FAT16B:
+ case MBR_PTYPE_SPEEDSTOR_16S:
+ case MBR_PTYPE_EFI:
+ info->fs_type = FS_MSDOS;
+ break;
+ case MBR_PTYPE_XENIX_ROOT:
+ case MBR_PTYPE_XENIX_USR:
+ info->fs_type = FS_SYSV;
+ break;
+ case MBR_PTYPE_NTFS:
+ info->fs_type = FS_NTFS;
+ break;
+ case MBR_PTYPE_APPLE_HFS:
+ info->fs_type = FS_HFS;
+ break;
+ case MBR_PTYPE_VMWARE:
+ info->fs_type = FS_VMFS;
+ break;
+ case MBR_PTYPE_AST_SWAP:
+ case MBR_PTYPE_DRDOS_LSWAP:
+ case MBR_PTYPE_LNXSWAP:
+ case MBR_PTYPE_BSDI_SWAP:
+ case MBR_PTYPE_HID_LNX_SWAP:
+ case MBR_PTYPE_VMWARE_SWAP:
+ info->fs_type = FS_SWAP;
+ break;
+ }
+ }
return true;
}
static bool
+get_wedge_devname(const struct disk_partitions *arg, part_id id,
+ const mbr_info_t *mb, int i, bool primary,
+ const struct mbr_partition *mp, void *cookie)
+{
+ char **res = cookie;
+
+ if (!res)
+ return false;
+
+ *res = __UNCONST(mb->wedge[i]);
+ return true;
+}
+
+static bool
+mbr_part_get_wedge(const struct disk_partitions *arg, part_id id,
+ char **res)
+{
+ return mbr_part_apply(arg, id, get_wedge_devname, res);
+}
+
+static bool
mbr_get_part_info(const struct disk_partitions *arg, part_id id,
struct disk_part_info *info)
{
@@ -2382,17 +2470,49 @@ mbr_can_add_partition(const struct disk_
}
static void
+mbr_free_wedge(int *fd, const char *disk, const char *wedge)
+{
+ struct dkwedge_info dkw;
+ char diskpath[MAXPATHLEN];
+
+ if (*fd == -1)
+ *fd = opendisk(disk, O_RDWR, diskpath,
+ sizeof(diskpath), 0);
+ if (*fd != -1) {
+ memset(&dkw, 0, sizeof(dkw));
+ strlcpy(dkw.dkw_devname, wedge,
+ sizeof(dkw.dkw_devname));
+ ioctl(*fd, DIOCDWEDGE, &dkw);
+ }
+}
+
+static void
mbr_free(struct disk_partitions *arg)
{
struct mbr_disk_partitions *parts = (struct mbr_disk_partitions*)arg;
+ mbr_info_t *m;
+ int i, fd;
assert(parts != NULL);
+ fd = -1;
+ m = &parts->mbr;
+ do {
+ for (i = 0; i < MBR_PART_COUNT; i++) {
+ if (m->wedge[i][0] != 0)
+ mbr_free_wedge(&fd, arg->disk, m->wedge[i]);
+ }
+ } while ((m = m->extended));
+
+ if (fd != -1)
+ close(fd);
+
if (parts->dlabel)
parts->dlabel->pscheme->free(parts->dlabel);
free_mbr_info(parts->mbr.extended);
free_last_mounted(&parts->mbr);
+ free(__UNCONST(parts->dp.disk));
free(parts);
}
@@ -2677,6 +2797,103 @@ mbr_part_alignment(const struct disk_par
}
static bool
+add_wedge(const char *disk, daddr_t start, daddr_t size,
+ char *wname, size_t max_len)
+{
+ struct dkwedge_info dkw;
+ char diskpath[MAXPATHLEN];
+ int fd;
+
+ memset(&dkw, 0, sizeof(dkw));
+ dkw.dkw_offset = start;
+ dkw.dkw_size = size;
+ snprintf((char*)dkw.dkw_wname, sizeof dkw.dkw_wname,
+ "%s_%" PRIi64 "@%" PRIi64, (const char*)disk, size, start);
+
+ *wname = 0;
+
+ fd = opendisk(disk, O_RDWR, diskpath, sizeof(diskpath), 0);
+ if (fd < 0)
+ return false;
+ if (ioctl(fd, DIOCAWEDGE, &dkw) == -1) {
+ close(fd);
+ return false;
+ }
+ close(fd);
+ strlcpy(wname, dkw.dkw_devname, max_len);
+ return true;
+}
+
+static bool
+mbr_get_part_device(const struct disk_partitions *arg,
+ part_id ptn, char *devname, size_t max_devname_len, int *part,
+ enum dev_name_usage usage, bool with_path)
+{
+ const struct mbr_disk_partitions *parts =
+ (const struct mbr_disk_partitions*)arg;
+ struct disk_part_info info, tmp;
+ part_id dptn;
+ char *wedge_dev;
+
+ if (!mbr_get_part_info(arg, ptn, &info))
+ return false;
+
+ if (!mbr_part_get_wedge(arg, ptn, &wedge_dev) || wedge_dev == NULL)
+ return false;
+
+ if (wedge_dev[0] == 0) {
+ /*
+ * If we have secondary partitions, try to find a match there
+ * and use that...
+ */
+ if (parts->dlabel != NULL) {
+ for (dptn = 0; dptn < parts->dlabel->num_part; dptn++) {
+ if (!parts->dlabel->pscheme->get_part_info(
+ parts->dlabel, dptn, &tmp))
+ continue;
+ if (tmp.start != info.start ||
+ tmp.size != info.size)
+ continue;
+ return parts->dlabel->pscheme->get_part_device(
+ parts->dlabel, dptn, devname,
+ max_devname_len,
+ part, usage, with_path);
+ }
+ }
+
+ /*
+ * Configure a new wedge and remember the name
+ */
+ if (!add_wedge(arg->disk, info.start, info.size, wedge_dev,
+ MBR_DEV_LEN))
+ return false;
+ }
+
+ assert(wedge_dev[0] != 0);
+
+ switch (usage) {
+ case logical_name:
+ case plain_name:
+ if (with_path)
+ snprintf(devname, max_devname_len, _PATH_DEV "%s",
+ wedge_dev);
+ else
+ strlcpy(devname, wedge_dev, max_devname_len);
+ return true;
+ case raw_dev_name:
+ if (with_path)
+ snprintf(devname, max_devname_len, _PATH_DEV "r%s",
+ wedge_dev);
+ else
+ snprintf(devname, max_devname_len, "r%s",
+ wedge_dev);
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool
is_custom_attribute_writable(const struct disk_partitions *arg, part_id id,
const mbr_info_t *mb, int i, bool primary,
const struct mbr_partition *mp, void *cookie)
@@ -2766,16 +2983,19 @@ mbr_parts = {
.custom_attribute_toggle = mbr_custom_attribute_toggle,
.custom_attribute_set_str = mbr_custom_attribute_set_str,
.get_part_types_count = mbr_get_part_type_count,
+ .adapt_foreign_part_info = generic_adapt_foreign_part_info,
.get_part_type = mbr_get_part_type,
.get_fs_part_type = mbr_get_fs_part_type,
.get_generic_part_type = mbr_get_generic_part_type,
.create_custom_part_type = mbr_custom_part_type,
+ .create_unknown_part_type = mbr_create_unknown_part_type,
.secondary_partitions = mbr_read_disklabel,
.write_to_disk = mbr_write_to_disk,
.read_from_disk = mbr_read_from_disk,
.create_new_for_disk = mbr_create_new,
.guess_disk_geom = mbr_guess_geom,
.change_disk_geom = mbr_change_disk_geom,
+ .get_part_device = mbr_get_part_device,
.max_free_space_at = mbr_max_part_size,
.get_free_spaces = mbr_get_free_spaces,
.set_part_info = mbr_set_part_info,
Index: src/usr.sbin/sysinst/msg.mi.fr
diff -u src/usr.sbin/sysinst/msg.mi.fr:1.21 src/usr.sbin/sysinst/msg.mi.fr:1.22
--- src/usr.sbin/sysinst/msg.mi.fr:1.21 Thu Oct 17 08:54:50 2019
+++ src/usr.sbin/sysinst/msg.mi.fr Tue Nov 12 16:33:14 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: msg.mi.fr,v 1.21 2019/10/17 08:54:50 maxv Exp $ */
+/* $NetBSD: msg.mi.fr,v 1.22 2019/11/12 16:33:14 martin Exp $ */
/*
* Copyright 1997 Piermont Information Systems Inc.
@@ -1336,6 +1336,7 @@ message dl_type_invalid {Invalid file sy
message cancel {Annuler}
message out_of_range {Invalid value}
+message invalid_guid {Invalid GUID}
message reedit_partitions {Re-edit}
message abort_installation {Abort installation}
@@ -1490,6 +1491,8 @@ message newfs_flag {N}
message ptn_install {installation}
message ptn_instflag_desc {(I)nstallation, }
+message clone_flag {C}
+message clone_flag_desc {, (C)lone}
message parttype_gpt {Guid Partition Table (GPT)}
message parttype_gpt_short {GPT}
@@ -1516,3 +1519,15 @@ message size_ptn_not_mounted {(Other: $
message running_system {current system}
+message clone_from_elsewhere {Clone external partition(s)}
+message select_foreign_part
+{Please select an external source partition:}
+message select_source_hdr
+{Your currently selected source partitions are:}
+message clone_with_data {Clone with data}
+message select_source_add {Add another partition}
+message clone_target_end {Add at end}
+message clone_target_hdr
+{Insert cloned partitions before:}
+message clone_target_disp {cloned partition(s)}
+
Index: src/usr.sbin/sysinst/mbr.h
diff -u src/usr.sbin/sysinst/mbr.h:1.3 src/usr.sbin/sysinst/mbr.h:1.4
--- src/usr.sbin/sysinst/mbr.h:1.3 Wed Jun 19 17:32:31 2019
+++ src/usr.sbin/sysinst/mbr.h Tue Nov 12 16:33:14 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: mbr.h,v 1.3 2019/06/19 17:32:31 martin Exp $ */
+/* $NetBSD: mbr.h,v 1.4 2019/11/12 16:33:14 martin Exp $ */
/*
* Copyright 1997, 1988 Piermont Information Systems Inc.
@@ -54,6 +54,8 @@
#define MBR_PUT_LSCYL(c) ((c) & 0xff)
#define MBR_PUT_MSCYLANDSEC(c,s) (((s) & 0x3f) | (((c) >> 2) & 0xc0))
+#define MBR_DEV_LEN 16 /* for wedge names */
+
typedef struct mbr_info_t mbr_info_t;
struct mbr_info_t {
struct mbr_sector mbr;
@@ -69,6 +71,8 @@ struct mbr_info_t {
/* only in first item... */
uint bootsec; /* start sector of bootmenu default */
#endif
+ /* for temporary access */
+ char wedge[MBR_PART_COUNT][MBR_DEV_LEN];
};
#ifdef BOOTSEL
Index: src/usr.sbin/sysinst/msg.mi.de
diff -u src/usr.sbin/sysinst/msg.mi.de:1.16 src/usr.sbin/sysinst/msg.mi.de:1.17
--- src/usr.sbin/sysinst/msg.mi.de:1.16 Wed Oct 2 11:16:04 2019
+++ src/usr.sbin/sysinst/msg.mi.de Tue Nov 12 16:33:14 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: msg.mi.de,v 1.16 2019/10/02 11:16:04 maya Exp $ */
+/* $NetBSD: msg.mi.de,v 1.17 2019/11/12 16:33:14 martin Exp $ */
/*
* Copyright 1997 Piermont Information Systems Inc.
@@ -318,7 +318,7 @@ message fspart
{Nachfolgend sehen Sie Ihre $2 Partitionen f�r $0.
Dies ist die letzte Chance, diese zu �ndern.
-Flags: $3(F)ormatieren$4. Gesamtgr��e: $5, noch frei: $6}
+Flags: $3(F)ormatieren$4. Gesamtgr��e: $5, frei: $6}
message ptnheaders_start {Start}
message ptnheaders_end {Ende}
@@ -1302,6 +1302,7 @@ message custom_type {Unbekannt}
message cancel {Abbrechen}
message out_of_range {Ung�ltiger Wert}
+message invalid_guid {Ung�ltige GUID}
message reedit_partitions {Erneut bearbeiten}
message abort_installation {Installation abbrechen}
@@ -1459,6 +1460,9 @@ W�hlen Sie die Partition, die Sie ver�nd
message ptn_install {Installation}
message ptn_instflag_desc {(I)nstalllieren, }
+message clone_flag {C}
+message clone_flag_desc {, (C)lone}
+
message parttype_gpt {Guid Partition Table (GPT)}
message parttype_gpt_short {GPT}
@@ -1483,3 +1487,14 @@ message gpt_flag_desc {, (S)tart}
message size_ptn_not_mounted {(Sonstige: $0)}
message running_system {aktuelles System}
+
+message clone_from_elsewhere {Externe Partition(en) duplizieren}
+message select_foreign_part {W�hlen Sie eine Quellpartition:}
+message select_source_hdr
+{Zur Zeit ausgw�hlte Quellpartitionen:}
+message clone_with_data {Auch die Inhalte duplizieren}
+message select_source_add {Weitere Partition hinzuf�gen}
+message clone_target_end {Als letzte hinzuf�gen}
+message clone_target_hdr
+{Einf�gen der duplizierten Partitionen vor:}
+message clone_target_disp {duplizierte Partition(en)}
Index: src/usr.sbin/sysinst/msg.mi.en
diff -u src/usr.sbin/sysinst/msg.mi.en:1.23 src/usr.sbin/sysinst/msg.mi.en:1.24
--- src/usr.sbin/sysinst/msg.mi.en:1.23 Thu Oct 17 08:54:50 2019
+++ src/usr.sbin/sysinst/msg.mi.en Tue Nov 12 16:33:14 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: msg.mi.en,v 1.23 2019/10/17 08:54:50 maxv Exp $ */
+/* $NetBSD: msg.mi.en,v 1.24 2019/11/12 16:33:14 martin Exp $ */
/*
* Copyright 1997 Piermont Information Systems Inc.
@@ -307,7 +307,7 @@ message fspart
{We now have your $2 partitions for $0 below.
This is your last chance to change them.
-Flags: $3(N)ewfs$4. Total size: $5, free space: $6}
+Flags: $3(N)ewfs$4. Total size: $5, free: $6}
message ptnheaders_start {Start}
message ptnheaders_end {End}
@@ -1234,6 +1234,7 @@ message dl_type_invalid {Invalid file sy
message cancel {Cancel}
message out_of_range {Invalid value}
+message invalid_guid {Invalid GUID}
message reedit_partitions {Re-edit}
message abort_installation {Abort installation}
@@ -1395,6 +1396,9 @@ Select the partition you wish to change:
message install_flag {I}
message newfs_flag {N}
+message clone_flag {C}
+message clone_flag_desc {, (C)lone}
+
message ptn_install {install}
message ptn_instflag_desc {(I)nstall, }
@@ -1423,3 +1427,15 @@ message size_ptn_not_mounted {(Other: $
message running_system {current system}
+message clone_from_elsewhere {Clone external partition(s)}
+message select_foreign_part
+{Please select an external source partition:}
+message select_source_hdr
+{Your currently selected source partitions are:}
+message clone_with_data {Clone with data}
+message select_source_add {Add another partition}
+message clone_target_end {Add at end}
+message clone_target_hdr
+{Insert cloned partitions before:}
+message clone_target_disp {cloned partition(s)}
+
Index: src/usr.sbin/sysinst/msg.mi.pl
diff -u src/usr.sbin/sysinst/msg.mi.pl:1.24 src/usr.sbin/sysinst/msg.mi.pl:1.25
--- src/usr.sbin/sysinst/msg.mi.pl:1.24 Wed Oct 23 18:08:31 2019
+++ src/usr.sbin/sysinst/msg.mi.pl Tue Nov 12 16:33:14 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: msg.mi.pl,v 1.24 2019/10/23 18:08:31 kamil Exp $ */
+/* $NetBSD: msg.mi.pl,v 1.25 2019/11/12 16:33:14 martin Exp $ */
/* Based on english version: */
/* NetBSD: msg.mi.pl,v 1.36 2004/04/17 18:55:35 atatat Exp */
@@ -1234,6 +1234,7 @@ message dl_type_invalid {Nieznany typ sy
message cancel {Anuluj}
message out_of_range {Nieprawidlowa wartosc}
+message invalid_guid {Nieprawidlowa GUID}
message reedit_partitions {Edytuj ponownie}
message abort_installation {Anuluj instalacje}
@@ -1385,6 +1386,8 @@ message newfs_flag {N}
message ptn_install {do instalacji}
message ptn_instflag_desc {(I)nstalacja, }
+message clone_flag {C}
+message clone_flag_desc {, (C)lone}
message parttype_gpt {Guid Partition Table (GPT)}
message parttype_gpt_short {GPT}
@@ -1411,3 +1414,15 @@ message size_ptn_not_mounted {(Inna: $0
message running_system {current system}
+message clone_from_elsewhere {Clone external partition(s)}
+message select_foreign_part
+{Please select an external source partition:}
+message select_source_hdr
+{Your currently selected source partitions are:}
+message clone_with_data {Clone with data}
+message select_source_add {Add another partition}
+message clone_target_end {Add at end}
+message clone_target_hdr
+{Insert cloned partitions before:}
+message clone_target_disp {cloned partition(s)}
+
Index: src/usr.sbin/sysinst/part_edit.c
diff -u src/usr.sbin/sysinst/part_edit.c:1.10 src/usr.sbin/sysinst/part_edit.c:1.11
--- src/usr.sbin/sysinst/part_edit.c:1.10 Sat Oct 26 07:32:52 2019
+++ src/usr.sbin/sysinst/part_edit.c Tue Nov 12 16:33:14 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: part_edit.c,v 1.10 2019/10/26 07:32:52 martin Exp $ */
+/* $NetBSD: part_edit.c,v 1.11 2019/11/12 16:33:14 martin Exp $ */
/*
* Copyright (c) 2019 The NetBSD Foundation, Inc.
@@ -57,8 +57,19 @@ struct part_edit_info {
bool num_changed; /* number of partitions has changed */
};
+struct single_clone_data {
+ struct selected_partitions clone_src;
+ part_id *clone_ids; /* partition IDs in target */
+};
+struct outer_parts_data {
+ struct arg_rv av;
+ struct single_clone_data *clones;
+ size_t num_clone_entries;
+};
+
static menu_ent *part_menu_opts; /* the currently edited partitions */
static menu_ent *outer_fill_part_menu_opts(const struct disk_partitions *parts, size_t *cnt);
+static void draw_outer_part_line(menudesc *m, int opt, void *arg);
static char outer_part_sep_line[MENUSTRSIZE],
outer_part_title[2*MENUSTRSIZE];
@@ -388,15 +399,16 @@ fill_part_edit_menu_opts(struct disk_par
static int
edit_part_entry(menudesc *m, void *arg)
{
- arg_rv *av = arg;
- struct part_edit_info data = { .parts = av->arg, .cur_id = m->cursel,
+ struct outer_parts_data *pdata = arg;
+ struct part_edit_info data = { .parts = pdata->av.arg,
+ .cur_id = m->cursel,
.first_custom_opt = __arraycount(common_ptn_edit_opts) };
int ptn_menu;
const char *err;
menu_ent *opts;
size_t num_opts;
- opts = fill_part_edit_menu_opts(av->arg, true, ptn_edit_opts,
+ opts = fill_part_edit_menu_opts(data.parts, true, ptn_edit_opts,
__arraycount(ptn_edit_opts), &num_opts);
if (opts == NULL)
return 1;
@@ -434,10 +446,120 @@ edit_part_entry(menudesc *m, void *arg)
}
static int
+add_part_clone(menudesc *menu, void *arg)
+{
+ struct outer_parts_data *pdata = arg;
+ struct disk_partitions *parts = pdata->av.arg;
+ struct clone_target_menu_data data;
+ menu_ent *men;
+ int num_men, i;
+ struct disk_part_info sinfo, cinfo;
+ struct disk_partitions *csrc;
+ struct disk_part_free_space space;
+ daddr_t offset, align;
+ size_t s, clone_cnt;
+ part_id cid;
+ struct selected_partitions selected;
+ struct single_clone_data *new_clones;
+
+ if (!select_partitions(&selected, parts))
+ return 0;
+
+ new_clones = realloc(pdata->clones,
+ sizeof(*pdata->clones)*(pdata->num_clone_entries+1));
+ if (new_clones == NULL)
+ return 0;
+ pdata->num_clone_entries++;
+ pdata->clones = new_clones;
+ new_clones += (pdata->num_clone_entries-1);
+ memset(new_clones, 0, sizeof *new_clones);
+ new_clones->clone_src = selected;
+
+ memset(&data, 0, sizeof data);
+ data.usage.parts = parts;
+
+ /* if we already have partitions, ask for the target position */
+ if (parts->num_part > 0) {
+ data.res = -1;
+ num_men = parts->num_part+1;
+ men = calloc(num_men, sizeof *men);
+ if (men == NULL)
+ return 0;
+ for (i = 0; i < num_men; i++)
+ men[i].opt_action = clone_target_select;
+ men[num_men-1].opt_name = MSG_clone_target_end;
+
+ data.usage.menu = new_menu(MSG_clone_target_hdr,
+ men, num_men, 3, 2, 0, 65, MC_SCROLL,
+ NULL, draw_outer_part_line, NULL, NULL, MSG_cancel);
+ process_menu(data.usage.menu, &data);
+ free_menu(data.usage.menu);
+ free(men);
+
+ if (data.res < 0)
+ goto err;
+ } else {
+ data.res = 0;
+ }
+
+ /* find selected offset from data.res and insert clones there */
+ align = parts->pscheme->get_part_alignment(parts);
+ offset = -1;
+ if (data.res > 0) {
+ for (cid = 0; cid < (size_t)data.res; cid++) {
+ if (!parts->pscheme->get_part_info(parts, cid, &sinfo))
+ continue;
+ offset = sinfo.start + sinfo.size;
+ }
+ } else {
+ offset = 0;
+ }
+
+ new_clones->clone_ids = calloc(selected.num_sel,
+ sizeof(*new_clones->clone_ids));
+ if (new_clones->clone_ids == NULL)
+ goto err;
+ for (s = 0; s < selected.num_sel; s++) {
+ csrc = selected.selection[s].parts;
+ cid = selected.selection[s].id;
+ csrc->pscheme->get_part_info(csrc, cid, &sinfo);
+ if (!parts->pscheme->adapt_foreign_part_info(
+ parts, &cinfo, csrc->pscheme, &sinfo))
+ continue;
+ size_t cnt = parts->pscheme->get_free_spaces(
+ parts, &space, 1, cinfo.size-align, align,
+ offset, -1);
+ if (cnt == 0)
+ continue;
+ cinfo.start = space.start;
+ cid = parts->pscheme->add_partition(
+ parts, &cinfo, NULL);
+ new_clones->clone_ids[s] = cid;
+ if (cid == NO_PART)
+ continue;
+ parts->pscheme->get_part_info(parts, cid, &cinfo);
+ clone_cnt++;
+ offset = rounddown(cinfo.start+cinfo.size+align, align);
+ }
+
+ /* reload menu and start again */
+ menu_opts_reload(menu, parts);
+ menu->cursel = parts->num_part+1;
+ if (parts->num_part == 0)
+ menu->cursel++;
+ return -1;
+
+err:
+ free_selected_partitions(&selected);
+ return -1;
+}
+
+
+static int
add_part_entry(menudesc *m, void *arg)
{
- arg_rv *av = arg;
- struct part_edit_info data = { .parts = av->arg,
+ struct outer_parts_data *pdata = arg;
+ struct part_edit_info data = { .parts = pdata->av.arg,
.first_custom_opt = PTN_OPTS_COMMON };
int ptn_menu;
daddr_t ptn_alignment;
@@ -446,7 +568,7 @@ add_part_entry(menudesc *m, void *arg)
struct disk_part_free_space space;
const char *err;
- opts = fill_part_edit_menu_opts(av->arg, false, ptn_add_opts,
+ opts = fill_part_edit_menu_opts(data.parts, false, ptn_add_opts,
__arraycount(ptn_add_opts), &num_opts);
if (opts == NULL)
return 1;
@@ -617,8 +739,8 @@ draw_outer_ptn_header(menudesc *m, void
static void
draw_outer_part_line(menudesc *m, int opt, void *arg)
{
- arg_rv *args = arg;
- struct disk_partitions *parts = args->arg;
+ struct outer_parts_data *pdata = arg;
+ struct disk_partitions *parts = pdata->av.arg;
int len;
part_id pno = opt;
struct disk_part_info info;
@@ -677,9 +799,9 @@ draw_outer_part_line(menudesc *m, int op
static int
part_edit_abort(menudesc *m, void *arg)
{
- arg_rv *args = arg;
+ struct outer_parts_data *pdata = arg;
- args->rv = -1;
+ pdata->av.rv = -1;
return 0;
}
@@ -692,7 +814,7 @@ outer_fill_part_menu_opts(const struct d
bool may_add;
may_add = parts->pscheme->can_add_partition(parts);
- num_opts = 3 + parts->num_part;
+ num_opts = 4 + parts->num_part;
if (parts->num_part == 0)
num_opts++;
if (may_add)
@@ -730,6 +852,11 @@ outer_fill_part_menu_opts(const struct d
op++;
}
+ /* and a partition cloner */
+ op->opt_name = MSG_clone_from_elsewhere;
+ op->opt_action = add_part_clone;
+ op++;
+
/* and unit changer */
op->opt_name = MSG_askunits;
op->opt_menu = MENU_sizechoice;
@@ -743,6 +870,9 @@ outer_fill_part_menu_opts(const struct d
op->opt_action = part_edit_abort;
op++;
+ /* counts are consistent? */
+ assert((op - opts) >= 0 && (size_t)(op - opts) == num_opts);
+
*cnt = num_opts;
return opts;
}
@@ -750,8 +880,8 @@ outer_fill_part_menu_opts(const struct d
static void
draw_outer_part_header(menudesc *m, void *arg)
{
- arg_rv *av = arg;
- struct disk_partitions *parts = av->arg;
+ struct outer_parts_data *pdata = arg;
+ struct disk_partitions *parts = pdata->av.arg;
char start[SSTRSIZE], size[SSTRSIZE], col[SSTRSIZE],
*disk_info, total[SSTRSIZE], avail[SSTRSIZE];
size_t sep;
@@ -1028,8 +1158,8 @@ ask_outer_partsizes(struct disk_partitio
{
int j;
int part_menu;
- size_t num_opts;
- arg_rv av;
+ size_t num_opts, i, ci;
+ struct outer_parts_data data;
part_menu_opts = outer_fill_part_menu_opts(parts, &num_opts);
part_menu = new_menu(outer_part_title, part_menu_opts, num_opts,
@@ -1048,18 +1178,18 @@ ask_outer_partsizes(struct disk_partitio
pm->current_cylsize = 16065; /* noone cares nowadays */
pm->ptstart = 0;
pm->ptsize = 0;
- av.rv = 0;
+ memset(&data, 0, sizeof data);
+ data.av.arg = parts;
for (;;) {
- av.arg = parts;
- av.rv = 0;
- process_menu(part_menu, &av);
- if (av.rv < 0)
+ data.av.rv = 0;
+ process_menu(part_menu, &data);
+ if (data.av.rv < 0)
break;
j = verify_outer_parts(parts, false);
if (j == 0) {
- av.rv = -1;
+ data.av.rv = -1;
return false;
} else if (j == 1) {
continue;
@@ -1067,10 +1197,29 @@ ask_outer_partsizes(struct disk_partitio
break;
}
+ /* handle cloned partitions content copies now */
+ for (i = 0; i < data.num_clone_entries; i++) {
+ for (ci = 0; ci < data.clones[i].clone_src.num_sel; ci++) {
+ if (data.clones[i].clone_src.with_data)
+ clone_partition_data(parts,
+ data.clones[i].clone_ids[ci],
+ data.clones[i].clone_src.selection[ci].
+ parts,
+ data.clones[i].clone_src.selection[ci].id);
+ }
+ }
+
+ /* free clone data */
+ if (data.clones) {
+ for (i = 0; i < data.num_clone_entries; i++)
+ free_selected_partitions(&data.clones[i].clone_src);
+ free(data.clones);
+ }
+
free_menu(part_menu);
free(part_menu_opts);
- return av.rv == 0;
+ return data.av.rv == 0;
}
bool
Index: src/usr.sbin/sysinst/partitions.c
diff -u src/usr.sbin/sysinst/partitions.c:1.4 src/usr.sbin/sysinst/partitions.c:1.5
--- src/usr.sbin/sysinst/partitions.c:1.4 Sat Oct 26 07:32:52 2019
+++ src/usr.sbin/sysinst/partitions.c Tue Nov 12 16:33:14 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: partitions.c,v 1.4 2019/10/26 07:32:52 martin Exp $ */
+/* $NetBSD: partitions.c,v 1.5 2019/11/12 16:33:14 martin Exp $ */
/*
* Copyright 2018 The NetBSD Foundation, Inc.
@@ -65,6 +65,34 @@ partitions_read_disk(const char *dev, da
return NULL;
}
+bool
+generic_adapt_foreign_part_info(const struct disk_partitions *myself,
+ struct disk_part_info *dest,
+ const struct disk_partitioning_scheme *src_scheme,
+ const struct disk_part_info *src)
+{
+ *dest = *src;
+ if (myself->pscheme == src_scheme)
+ return true; /* no conversion needed */
+
+ if (src->nat_type == NULL)
+ return false;
+
+ /* slightly simplistic, enhance when needed */
+ dest->nat_type = myself->pscheme->get_fs_part_type(dest->fs_type,
+ dest->fs_sub_type);
+ if (dest->nat_type == NULL)
+ dest->nat_type = myself->pscheme->get_generic_part_type(
+ src->nat_type->generic_ptype);
+ if (dest->nat_type == NULL)
+ dest->nat_type = myself->pscheme->create_unknown_part_type();
+ if (dest->nat_type == NULL)
+ dest->nat_type = myself->pscheme->get_generic_part_type(
+ PT_unknown);
+
+ return true;
+}
+
/*************** global init ****************************************/
/*
* Helper structure to fill our global list of available partitioning
@@ -171,3 +199,15 @@ static const struct part_scheme_desc all
free(is_available);
}
+
+/*
+ * Final cleanup
+ */
+void
+partitions_cleanup(void)
+{
+ for (size_t i = 0; i < num_available_part_schemes; i++)
+ if (available_part_schemes[i]->cleanup != NULL)
+ available_part_schemes[i]->cleanup();
+ free(available_part_schemes);
+}
Index: src/usr.sbin/sysinst/partitions.h
diff -u src/usr.sbin/sysinst/partitions.h:1.7 src/usr.sbin/sysinst/partitions.h:1.8
--- src/usr.sbin/sysinst/partitions.h:1.7 Fri Oct 25 12:49:58 2019
+++ src/usr.sbin/sysinst/partitions.h Tue Nov 12 16:33:14 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: partitions.h,v 1.7 2019/10/25 12:49:58 martin Exp $ */
+/* $NetBSD: partitions.h,v 1.8 2019/11/12 16:33:14 martin Exp $ */
/*
* Copyright 2018 The NetBSD Foundation, Inc.
@@ -233,6 +233,15 @@ struct disk_partitioning_scheme {
*/
const struct part_type_desc * (*create_custom_part_type)
(const char *custom, const char **err_msg);
+ /*
+ * Return a usable internal partition type representation
+ * for types that are not otherwise mappable.
+ * This could be FS_OTHER for disklabel, or a randomly
+ * created type guid for GPT. This type may or may not be
+ * in the regular type list. If not, it needs to behave like a
+ * custom type.
+ */
+ const struct part_type_desc * (*create_unknown_part_type)(void);
/*
* Global attributes
@@ -343,8 +352,10 @@ struct disk_partitioning_scheme {
* This mostly adjusts flags and partition type pointers (using
* more lose matching than add_partition would do).
*/
- bool (*adapt_foreign_part_info)(const struct disk_partitions*,
- const struct disk_part_info *src, struct disk_part_info *dest);
+ bool (*adapt_foreign_part_info)(
+ const struct disk_partitions *myself, struct disk_part_info *dest,
+ const struct disk_partitioning_scheme *src_scheme,
+ const struct disk_part_info *src);
/*
* Update data for an existing partition
@@ -491,6 +502,9 @@ struct disk_partitioning_scheme {
/* Free all the data */
void (*free)(struct disk_partitions*);
+
+ /* Scheme global cleanup */
+ void (*cleanup)(void);
};
/*
@@ -552,6 +566,16 @@ struct disk_partitions *
partitions_read_disk(const char *, daddr_t disk_size, bool no_mbr);
/*
- * One time initialization
+ * Generic part info adaption, may be overriden by individual partitionin
+ * schemes
+ */
+bool generic_adapt_foreign_part_info(
+ const struct disk_partitions *myself, struct disk_part_info *dest,
+ const struct disk_partitioning_scheme *src_scheme,
+ const struct disk_part_info *src);
+
+/*
+ * One time initialization and clenaup
*/
void partitions_init(void);
+void partitions_cleanup(void);
Index: src/usr.sbin/sysinst/util.c
diff -u src/usr.sbin/sysinst/util.c:1.34 src/usr.sbin/sysinst/util.c:1.35
--- src/usr.sbin/sysinst/util.c:1.34 Fri Oct 4 21:36:02 2019
+++ src/usr.sbin/sysinst/util.c Tue Nov 12 16:33:14 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: util.c,v 1.34 2019/10/04 21:36:02 mrg Exp $ */
+/* $NetBSD: util.c,v 1.35 2019/11/12 16:33:14 martin Exp $ */
/*
* Copyright 1997 Piermont Information Systems Inc.
@@ -2043,42 +2043,48 @@ usage_set_from_parts(struct partition_us
return usage_info_list_from_parts(&wanted->infos, &wanted->num, parts);
}
-bool
-install_desc_from_parts(struct install_partition_desc *install,
- struct disk_partitions *parts)
+struct disk_partitions *
+get_inner_parts(struct disk_partitions *parts)
{
- struct disk_partitions *inner_parts;
daddr_t start, size;
part_id pno;
struct disk_part_info info;
- memset(install, 0, sizeof(*install));
+ if (parts->pscheme->secondary_scheme == NULL)
+ return NULL;
- if (parts->pscheme->secondary_scheme != NULL) {
- start = -1;
- size = -1;
- if (parts->pscheme->guess_install_target != NULL &&
- parts->pscheme->guess_install_target(parts,
- &start, &size)) {
- } else {
- for (pno = 0; pno < parts->num_part; pno++) {
- if (!parts->pscheme->get_part_info(parts, pno,
- &info))
- continue;
- if (!(info.flags & PTI_SEC_CONTAINER))
- continue;
- start = info.start;
- size = info.size;
- }
- }
- if (size > 0) {
- inner_parts = parts->pscheme->secondary_partitions(
- parts, start, false);
- if (inner_parts != NULL)
- parts = inner_parts;
+ start = -1;
+ size = -1;
+ if (parts->pscheme->guess_install_target == NULL ||
+ !parts->pscheme->guess_install_target(parts, &start, &size)) {
+ for (pno = 0; pno < parts->num_part; pno++) {
+ if (!parts->pscheme->get_part_info(parts, pno, &info))
+ continue;
+ if (!(info.flags & PTI_SEC_CONTAINER))
+ continue;
+ start = info.start;
+ size = info.size;
}
}
+ if (size > 0)
+ return parts->pscheme->secondary_partitions(parts, start,
+ false);
+
+ return NULL;
+}
+
+bool
+install_desc_from_parts(struct install_partition_desc *install,
+ struct disk_partitions *parts)
+{
+ struct disk_partitions *inner_parts;
+
+ memset(install, 0, sizeof(*install));
+ inner_parts = get_inner_parts(parts);
+ if (inner_parts != NULL)
+ parts = inner_parts;
+
return usage_info_list_from_parts(&install->infos, &install->num,
parts);
}
@@ -2086,6 +2092,7 @@ install_desc_from_parts(struct install_p
void
free_usage_set(struct partition_usage_set *wanted)
{
+ /* XXX - free parts? free clone src? */
free(wanted->menu_opts);
free(wanted->infos);
}
@@ -2093,6 +2100,18 @@ free_usage_set(struct partition_usage_se
void
free_install_desc(struct install_partition_desc *install)
{
+ size_t i, j;
+
+ for (i = 0; i < install->num; i++) {
+ struct selected_partitions *src = install->infos[i].clone_src;
+ if (!(install->infos[i].flags & PUIFLG_CLONE_PARTS) ||
+ src == NULL)
+ continue;
+ free_selected_partitions(src);
+ for (j = i+1; j < install->num; j++)
+ if (install->infos[j].clone_src == src)
+ install->infos[j].clone_src = NULL;
+ }
free(install->infos);
}
Index: src/usr.sbin/sysinst/arch/i386/md.c
diff -u src/usr.sbin/sysinst/arch/i386/md.c:1.21 src/usr.sbin/sysinst/arch/i386/md.c:1.22
--- src/usr.sbin/sysinst/arch/i386/md.c:1.21 Wed Aug 14 12:55:36 2019
+++ src/usr.sbin/sysinst/arch/i386/md.c Tue Nov 12 16:33:14 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: md.c,v 1.21 2019/08/14 12:55:36 martin Exp $ */
+/* $NetBSD: md.c,v 1.22 2019/11/12 16:33:14 martin Exp $ */
/*
* Copyright 1997 Piermont Information Systems Inc.
@@ -895,7 +895,7 @@ x86_md_part_defaults(struct pm_devs *cur
if (info.nat_type->generic_ptype != boot->type)
continue;
boot->flags &= ~PUIFLAG_ADD_OUTER;
- boot->flags |= PUIFLG_IS_OUTER|PUIFLAG_ADD_INNER;
+ boot->flags |= PUIFLG_IS_OUTER|PUIFLG_ADD_INNER;
boot->size = info.size;
boot->cur_start = info.start;
boot->cur_flags = info.flags;