Sat Jul 17 11:32:50 2021 UTC ()
PR 56310: avoid assert() failures (or crashes) when the runtime addition
of a wedge fails (for whatever reasons).


(martin)
diff -r1.23 -r1.24 src/usr.sbin/sysinst/gpt.c
diff -r1.51 -r1.52 src/usr.sbin/sysinst/partman.c

cvs diff -r1.23 -r1.24 src/usr.sbin/sysinst/gpt.c (switch to unified diff)

--- src/usr.sbin/sysinst/gpt.c 2021/01/31 22:45:46 1.23
+++ src/usr.sbin/sysinst/gpt.c 2021/07/17 11:32:50 1.24
@@ -1,1855 +1,1858 @@ @@ -1,1855 +1,1858 @@
1/* $NetBSD: gpt.c,v 1.23 2021/01/31 22:45:46 rillig Exp $ */ 1/* $NetBSD: gpt.c,v 1.24 2021/07/17 11:32:50 martin Exp $ */
2 2
3/* 3/*
4 * Copyright 2018 The NetBSD Foundation, Inc. 4 * Copyright 2018 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS'' 16 * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE 19 * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26 * THE POSSIBILITY OF SUCH DAMAGE. 26 * THE POSSIBILITY OF SUCH DAMAGE.
27 * 27 *
28 */ 28 */
29 29
30#include "defs.h" 30#include "defs.h"
31#include "mbr.h" 31#include "mbr.h"
32#include "md.h" 32#include "md.h"
33#include "gpt_uuid.h" 33#include "gpt_uuid.h"
34#include <assert.h> 34#include <assert.h>
35#include <err.h> 35#include <err.h>
36#include <paths.h> 36#include <paths.h>
37#include <sys/param.h> 37#include <sys/param.h>
38#include <sys/ioctl.h> 38#include <sys/ioctl.h>
39#include <util.h> 39#include <util.h>
40#include <uuid.h> 40#include <uuid.h>
41 41
42bool gpt_parts_check(void); /* check for needed binaries */ 42bool gpt_parts_check(void); /* check for needed binaries */
43 43
44 44
45/*************** GPT ************************************************/ 45/*************** GPT ************************************************/
46/* a GPT based disk_partitions interface */ 46/* a GPT based disk_partitions interface */
47 47
48#define GUID_STR_LEN 40 48#define GUID_STR_LEN 40
49#define GPT_PTYPE_ALLOC 32 /* initial type array allocation, should be > 49#define GPT_PTYPE_ALLOC 32 /* initial type array allocation, should be >
50 * gpt type -l | wc -l */ 50 * gpt type -l | wc -l */
51#define GPT_DEV_LEN 16 /* dkNN */ 51#define GPT_DEV_LEN 16 /* dkNN */
52 52
53#define GPT_PARTS_PER_SEC 4 /* a 512 byte sector holds 4 entries */ 53#define GPT_PARTS_PER_SEC 4 /* a 512 byte sector holds 4 entries */
54#define GPT_DEFAULT_MAX_PARTS 128 54#define GPT_DEFAULT_MAX_PARTS 128
55 55
56/* a usable label will be short, so we can get away with an arbitrary limit */ 56/* a usable label will be short, so we can get away with an arbitrary limit */
57#define GPT_LABEL_LEN 96 57#define GPT_LABEL_LEN 96
58 58
59#define GPT_ATTR_BIOSBOOT 1 59#define GPT_ATTR_BIOSBOOT 1
60#define GPT_ATTR_BOOTME 2 60#define GPT_ATTR_BOOTME 2
61#define GPT_ATTR_BOOTONCE 4 61#define GPT_ATTR_BOOTONCE 4
62#define GPT_ATTR_BOOTFAILED 8 62#define GPT_ATTR_BOOTFAILED 8
63#define GPT_ATTR_NOBLOCKIO 16 63#define GPT_ATTR_NOBLOCKIO 16
64#define GPT_ATTR_REQUIRED 32 64#define GPT_ATTR_REQUIRED 32
65 65
66/* when we don't care for BIOS or UEFI boot, use the combined boot flags */ 66/* when we don't care for BIOS or UEFI boot, use the combined boot flags */
67#define GPT_ATTR_BOOT (GPT_ATTR_BIOSBOOT|GPT_ATTR_BOOTME) 67#define GPT_ATTR_BOOT (GPT_ATTR_BIOSBOOT|GPT_ATTR_BOOTME)
68 68
69struct gpt_attr_desc { 69struct gpt_attr_desc {
70 const char *name; 70 const char *name;
71 uint flag; 71 uint flag;
72}; 72};
73static const struct gpt_attr_desc gpt_avail_attrs[] = { 73static const struct gpt_attr_desc gpt_avail_attrs[] = {
74 { "biosboot", GPT_ATTR_BIOSBOOT }, 74 { "biosboot", GPT_ATTR_BIOSBOOT },
75 { "bootme", GPT_ATTR_BOOTME }, 75 { "bootme", GPT_ATTR_BOOTME },
76 { "bootonce", GPT_ATTR_BOOTONCE }, 76 { "bootonce", GPT_ATTR_BOOTONCE },
77 { "bootfailed", GPT_ATTR_BOOTFAILED }, 77 { "bootfailed", GPT_ATTR_BOOTFAILED },
78 { "noblockio", GPT_ATTR_NOBLOCKIO }, 78 { "noblockio", GPT_ATTR_NOBLOCKIO },
79 { "required", GPT_ATTR_REQUIRED }, 79 { "required", GPT_ATTR_REQUIRED },
80 { NULL, 0 } 80 { NULL, 0 }
81}; 81};
82 82
83struct gpt_ptype_desc { 83struct gpt_ptype_desc {
84 struct part_type_desc gent; 84 struct part_type_desc gent;
85 char tid[GUID_STR_LEN]; 85 char tid[GUID_STR_LEN];
86 uint fsflags, default_fs_type; 86 uint fsflags, default_fs_type;
87}; 87};
88 88
89static const 89static const
90struct { 90struct {
91 const char *name; 91 const char *name;
92 uint fstype; 92 uint fstype;
93 enum part_type ptype; 93 enum part_type ptype;
94 uint fsflags; 94 uint fsflags;
95} gpt_fs_types[] = { 95} gpt_fs_types[] = {
96 { .name = "ffs", .fstype = FS_BSDFFS, .ptype = PT_root, 96 { .name = "ffs", .fstype = FS_BSDFFS, .ptype = PT_root,
97 .fsflags = GLM_LIKELY_FFS }, 97 .fsflags = GLM_LIKELY_FFS },
98 { .name = "swap", .fstype = FS_SWAP, .ptype = PT_swap }, 98 { .name = "swap", .fstype = FS_SWAP, .ptype = PT_swap },
99 { .name = "windows", .fstype = FS_MSDOS, .ptype = PT_FAT, 99 { .name = "windows", .fstype = FS_MSDOS, .ptype = PT_FAT,
100 .fsflags = GLM_MAYBE_FAT32|GLM_MAYBE_NTFS }, 100 .fsflags = GLM_MAYBE_FAT32|GLM_MAYBE_NTFS },
101 { .name = "windows", .fstype = FS_NTFS, .ptype = PT_FAT, 101 { .name = "windows", .fstype = FS_NTFS, .ptype = PT_FAT,
102 .fsflags = GLM_MAYBE_FAT32|GLM_MAYBE_NTFS }, 102 .fsflags = GLM_MAYBE_FAT32|GLM_MAYBE_NTFS },
103 { .name = "efi", .fstype = FS_MSDOS, .ptype = PT_EFI_SYSTEM, 103 { .name = "efi", .fstype = FS_MSDOS, .ptype = PT_EFI_SYSTEM,
104 .fsflags = GLM_MAYBE_FAT32 }, 104 .fsflags = GLM_MAYBE_FAT32 },
105 { .name = "bios", .fstype = FS_MSDOS, .ptype = PT_FAT, 105 { .name = "bios", .fstype = FS_MSDOS, .ptype = PT_FAT,
106 .fsflags = GLM_MAYBE_FAT32 }, 106 .fsflags = GLM_MAYBE_FAT32 },
107 { .name = "lfs", .fstype = FS_BSDLFS, .ptype = PT_root }, 107 { .name = "lfs", .fstype = FS_BSDLFS, .ptype = PT_root },
108 { .name = "linux-data", .fstype = FS_EX2FS, .ptype = PT_root }, 108 { .name = "linux-data", .fstype = FS_EX2FS, .ptype = PT_root },
109 { .name = "apple", .fstype = FS_HFS, .ptype = PT_unknown }, 109 { .name = "apple", .fstype = FS_HFS, .ptype = PT_unknown },
110 { .name = "ccd", .fstype = FS_CCD, .ptype = PT_root }, 110 { .name = "ccd", .fstype = FS_CCD, .ptype = PT_root },
111 { .name = "cgd", .fstype = FS_CGD, .ptype = PT_root }, 111 { .name = "cgd", .fstype = FS_CGD, .ptype = PT_root },
112 { .name = "raid", .fstype = FS_RAID, .ptype = PT_root }, 112 { .name = "raid", .fstype = FS_RAID, .ptype = PT_root },
113 { .name = "vmcore", .fstype = FS_VMKCORE, .ptype = PT_unknown }, 113 { .name = "vmcore", .fstype = FS_VMKCORE, .ptype = PT_unknown },
114 { .name = "vmfs", .fstype = FS_VMFS, .ptype = PT_unknown }, 114 { .name = "vmfs", .fstype = FS_VMFS, .ptype = PT_unknown },
115 { .name = "vmresered", .fstype = FS_VMWRESV, .ptype = PT_unknown }, 115 { .name = "vmresered", .fstype = FS_VMWRESV, .ptype = PT_unknown },
116 { .name = "zfs", .fstype = FS_ZFS, .ptype = PT_root }, 116 { .name = "zfs", .fstype = FS_ZFS, .ptype = PT_root },
117}; 117};
118 118
119static size_t gpt_ptype_cnt = 0, gpt_ptype_alloc = 0; 119static size_t gpt_ptype_cnt = 0, gpt_ptype_alloc = 0;
120static struct gpt_ptype_desc *gpt_ptype_descs = NULL; 120static struct gpt_ptype_desc *gpt_ptype_descs = NULL;
121 121
122/* "well" known types with special handling */ 122/* "well" known types with special handling */
123static const struct part_type_desc *gpt_native_root; 123static const struct part_type_desc *gpt_native_root;
124 124
125/* similar to struct gpt_ent, but matching our needs */ 125/* similar to struct gpt_ent, but matching our needs */
126struct gpt_part_entry { 126struct gpt_part_entry {
127 const struct gpt_ptype_desc *gp_type; 127 const struct gpt_ptype_desc *gp_type;
128 char gp_id[GUID_STR_LEN]; /* partition guid as string */ 128 char gp_id[GUID_STR_LEN]; /* partition guid as string */
129 daddr_t gp_start, gp_size; 129 daddr_t gp_start, gp_size;
130 uint gp_attr; /* various attribute bits */ 130 uint gp_attr; /* various attribute bits */
131 char gp_label[GPT_LABEL_LEN]; /* user defined label */ 131 char gp_label[GPT_LABEL_LEN]; /* user defined label */
132 char gp_dev_name[GPT_DEV_LEN]; /* name of wedge */ 132 char gp_dev_name[GPT_DEV_LEN]; /* name of wedge */
133 const char *last_mounted; /* last mounted if known */ 133 const char *last_mounted; /* last mounted if known */
134 uint fs_type, fs_sub_type, /* FS_* and maybe sub type */ 134 uint fs_type, fs_sub_type, /* FS_* and maybe sub type */
135 fs_opt1, fs_opt2, fs_opt3; /* transient file system options */ 135 fs_opt1, fs_opt2, fs_opt3; /* transient file system options */
136 uint gp_flags; 136 uint gp_flags;
137#define GPEF_ON_DISK 1 /* This entry exists on-disk */ 137#define GPEF_ON_DISK 1 /* This entry exists on-disk */
138#define GPEF_MODIFIED 2 /* this entry has been changed */ 138#define GPEF_MODIFIED 2 /* this entry has been changed */
139#define GPEF_WEDGE 4 /* wedge for this exists */ 139#define GPEF_WEDGE 4 /* wedge for this exists */
140#define GPEF_RESIZED 8 /* size has changed */ 140#define GPEF_RESIZED 8 /* size has changed */
141#define GPEF_TARGET 16 /* marked install target */ 141#define GPEF_TARGET 16 /* marked install target */
142 struct gpt_part_entry *gp_next; 142 struct gpt_part_entry *gp_next;
143}; 143};
144 144
145static const struct gpt_ptype_desc *gpt_find_native_type( 145static const struct gpt_ptype_desc *gpt_find_native_type(
146 const struct part_type_desc *gent); 146 const struct part_type_desc *gent);
147static const struct gpt_ptype_desc *gpt_find_guid_type(const char*); 147static const struct gpt_ptype_desc *gpt_find_guid_type(const char*);
148static bool 148static bool
149gpt_info_to_part(struct gpt_part_entry *p, const struct disk_part_info *info, 149gpt_info_to_part(struct gpt_part_entry *p, const struct disk_part_info *info,
150 const char **err_msg); 150 const char **err_msg);
151 151
152const struct disk_partitioning_scheme gpt_parts; 152const struct disk_partitioning_scheme gpt_parts;
153struct gpt_disk_partitions { 153struct gpt_disk_partitions {
154 struct disk_partitions dp; 154 struct disk_partitions dp;
155 /* 155 /*
156 * We keep a list of our current valid partitions, pointed 156 * We keep a list of our current valid partitions, pointed
157 * to by "partitions". 157 * to by "partitions".
158 * dp.num_part is the number of entries in "partitions". 158 * dp.num_part is the number of entries in "partitions".
159 * When partitions that have a representation on disk already 159 * When partitions that have a representation on disk already
160 * are deleted, we move them to the "obsolete" list so we 160 * are deleted, we move them to the "obsolete" list so we
161 * can issue the proper commands to remove it when writing back. 161 * can issue the proper commands to remove it when writing back.
162 */ 162 */
163 struct gpt_part_entry *partitions, /* current partitions */ 163 struct gpt_part_entry *partitions, /* current partitions */
164 *obsolete; /* deleted partitions */ 164 *obsolete; /* deleted partitions */
165 size_t max_num_parts; /* how many entries max? */ 165 size_t max_num_parts; /* how many entries max? */
166 size_t prologue, epilogue; /* number of sectors res. */ 166 size_t prologue, epilogue; /* number of sectors res. */
167 bool has_gpt; /* disk already has a GPT */ 167 bool has_gpt; /* disk already has a GPT */
168}; 168};
169 169
170/* 170/*
171 * Init global variables from MD details 171 * Init global variables from MD details
172 */ 172 */
173static void 173static void
174gpt_md_init(bool is_boot_disk, size_t *max_parts, size_t *head, size_t *tail) 174gpt_md_init(bool is_boot_disk, size_t *max_parts, size_t *head, size_t *tail)
175{ 175{
176 size_t num; 176 size_t num;
177 177
178 if (is_boot_disk) { 178 if (is_boot_disk) {
179#ifdef MD_GPT_INITIAL_SIZE 179#ifdef MD_GPT_INITIAL_SIZE
180#if MD_GPT_INITIAL_SIZE < 2*512 180#if MD_GPT_INITIAL_SIZE < 2*512
181#error impossible small GPT prologue 181#error impossible small GPT prologue
182#endif 182#endif
183 num = ((MD_GPT_INITIAL_SIZE-(2*512))/512)*GPT_PARTS_PER_SEC; 183 num = ((MD_GPT_INITIAL_SIZE-(2*512))/512)*GPT_PARTS_PER_SEC;
184#else 184#else
185 num = GPT_DEFAULT_MAX_PARTS; 185 num = GPT_DEFAULT_MAX_PARTS;
186#endif 186#endif
187 } else { 187 } else {
188 num = GPT_DEFAULT_MAX_PARTS; 188 num = GPT_DEFAULT_MAX_PARTS;
189 } 189 }
190 *max_parts = num; 190 *max_parts = num;
191 *head = 2 + num/GPT_PARTS_PER_SEC; 191 *head = 2 + num/GPT_PARTS_PER_SEC;
192 *tail = 1 + num/GPT_PARTS_PER_SEC; 192 *tail = 1 + num/GPT_PARTS_PER_SEC;
193} 193}
194 194
195/* 195/*
196 * Parse a part of "gpt show" output into a struct gpt_part_entry. 196 * Parse a part of "gpt show" output into a struct gpt_part_entry.
197 * Output is from "show -a" format if details = false, otherwise 197 * Output is from "show -a" format if details = false, otherwise
198 * from details for a specific partition (show -i or show -b) 198 * from details for a specific partition (show -i or show -b)
199 */ 199 */
200static void 200static void
201gpt_add_info(struct gpt_part_entry *part, const char *tag, char *val, 201gpt_add_info(struct gpt_part_entry *part, const char *tag, char *val,
202 bool details) 202 bool details)
203{ 203{
204 char *s, *e; 204 char *s, *e;
205 205
206 if (details && strcmp(tag, "Start:") == 0) { 206 if (details && strcmp(tag, "Start:") == 0) {
207 part->gp_start = strtouq(val, NULL, 10); 207 part->gp_start = strtouq(val, NULL, 10);
208 } else if (details && strcmp(tag, "Size:") == 0) { 208 } else if (details && strcmp(tag, "Size:") == 0) {
209 part->gp_size = strtouq(val, NULL, 10); 209 part->gp_size = strtouq(val, NULL, 10);
210 } else if (details && strcmp(tag, "Type:") == 0) { 210 } else if (details && strcmp(tag, "Type:") == 0) {
211 s = strchr(val, '('); 211 s = strchr(val, '(');
212 if (!s) 212 if (!s)
213 return; 213 return;
214 e = strchr(s, ')'); 214 e = strchr(s, ')');
215 if (!e) 215 if (!e)
216 return; 216 return;
217 *e = 0; 217 *e = 0;
218 part->gp_type = gpt_find_guid_type(s+1); 218 part->gp_type = gpt_find_guid_type(s+1);
219 } else if (strcmp(tag, "TypeID:") == 0) { 219 } else if (strcmp(tag, "TypeID:") == 0) {
220 part->gp_type = gpt_find_guid_type(val); 220 part->gp_type = gpt_find_guid_type(val);
221 } else if (strcmp(tag, "GUID:") == 0) { 221 } else if (strcmp(tag, "GUID:") == 0) {
222 strlcpy(part->gp_id, val, sizeof(part->gp_id)); 222 strlcpy(part->gp_id, val, sizeof(part->gp_id));
223 } else if (strcmp(tag, "Label:") == 0) { 223 } else if (strcmp(tag, "Label:") == 0) {
224 strlcpy(part->gp_label, val, sizeof(part->gp_label)); 224 strlcpy(part->gp_label, val, sizeof(part->gp_label));
225 } else if (strcmp(tag, "Attributes:") == 0) { 225 } else if (strcmp(tag, "Attributes:") == 0) {
226 char *n; 226 char *n;
227 227
228 while ((n = strsep(&val, ", ")) != NULL) { 228 while ((n = strsep(&val, ", ")) != NULL) {
229 if (*n == 0) 229 if (*n == 0)
230 continue; 230 continue;
231 for (const struct gpt_attr_desc *p = gpt_avail_attrs; 231 for (const struct gpt_attr_desc *p = gpt_avail_attrs;
232 p->name != NULL; p++) { 232 p->name != NULL; p++) {
233 if (strcmp(p->name, n) == 0) 233 if (strcmp(p->name, n) == 0)
234 part->gp_attr |= p->flag; 234 part->gp_attr |= p->flag;
235 } 235 }
236 } 236 }
237 } 237 }
238} 238}
239 239
240/* 240/*
241 * Find the partition matching this wedge info and record that we 241 * Find the partition matching this wedge info and record that we
242 * have a wedge already. 242 * have a wedge already.
243 */ 243 */
244static void 244static void
245update_part_from_wedge_info(struct gpt_disk_partitions *parts, 245update_part_from_wedge_info(struct gpt_disk_partitions *parts,
246 const struct dkwedge_info *dkw) 246 const struct dkwedge_info *dkw)
247{ 247{
248 for (struct gpt_part_entry *p = parts->partitions; p != NULL; 248 for (struct gpt_part_entry *p = parts->partitions; p != NULL;
249 p = p->gp_next) { 249 p = p->gp_next) {
250 if (p->gp_start != dkw->dkw_offset || 250 if (p->gp_start != dkw->dkw_offset ||
251 (uint64_t)p->gp_size != dkw->dkw_size) 251 (uint64_t)p->gp_size != dkw->dkw_size)
252 continue; 252 continue;
253 p->gp_flags |= GPEF_WEDGE; 253 p->gp_flags |= GPEF_WEDGE;
254 strlcpy(p->gp_dev_name, dkw->dkw_devname, 254 strlcpy(p->gp_dev_name, dkw->dkw_devname,
255 sizeof p->gp_dev_name); 255 sizeof p->gp_dev_name);
256 return; 256 return;
257 } 257 }
258} 258}
259 259
260static struct disk_partitions * 260static struct disk_partitions *
261gpt_read_from_disk(const char *dev, daddr_t start, daddr_t len, size_t bps, 261gpt_read_from_disk(const char *dev, daddr_t start, daddr_t len, size_t bps,
262 const struct disk_partitioning_scheme *scheme) 262 const struct disk_partitioning_scheme *scheme)
263{ 263{
264 char diskpath[MAXPATHLEN]; 264 char diskpath[MAXPATHLEN];
265 int fd; 265 int fd;
266 struct dkwedge_info *dkw; 266 struct dkwedge_info *dkw;
267 struct dkwedge_list dkwl; 267 struct dkwedge_list dkwl;
268 size_t bufsize, dk; 268 size_t bufsize, dk;
269 269
270 assert(start == 0); 270 assert(start == 0);
271 assert(have_gpt); 271 assert(have_gpt);
272 272
273 if (run_program(RUN_SILENT | RUN_ERROR_OK, 273 if (run_program(RUN_SILENT | RUN_ERROR_OK,
274 "gpt -rq header %s", dev) != 0) 274 "gpt -rq header %s", dev) != 0)
275 return NULL; 275 return NULL;
276 276
277 /* read the partitions */ 277 /* read the partitions */
278 int i; 278 int i;
279 unsigned int p_index; 279 unsigned int p_index;
280 daddr_t p_start = 0, p_size = 0, avail_start = 0, avail_size = 0, 280 daddr_t p_start = 0, p_size = 0, avail_start = 0, avail_size = 0,
281 disk_size = 0; 281 disk_size = 0;
282 char *textbuf, *t, *tt, p_type[STRSIZE]; 282 char *textbuf, *t, *tt, p_type[STRSIZE];
283 static const char regpart_prefix[] = "GPT part - "; 283 static const char regpart_prefix[] = "GPT part - ";
284 struct gpt_disk_partitions *parts; 284 struct gpt_disk_partitions *parts;
285 struct gpt_part_entry *last = NULL, *add_to = NULL; 285 struct gpt_part_entry *last = NULL, *add_to = NULL;
286 const struct gpt_ptype_desc *native_root 286 const struct gpt_ptype_desc *native_root
287 = gpt_find_native_type(gpt_native_root); 287 = gpt_find_native_type(gpt_native_root);
288 bool have_target = false; 288 bool have_target = false;
289 289
290 if (collect(T_OUTPUT, &textbuf, "gpt -r show -a %s 2>/dev/null", dev) 290 if (collect(T_OUTPUT, &textbuf, "gpt -r show -a %s 2>/dev/null", dev)
291 < 1) 291 < 1)
292 return NULL; 292 return NULL;
293 293
294 /* parse output and create our list */ 294 /* parse output and create our list */
295 parts = calloc(1, sizeof(*parts)); 295 parts = calloc(1, sizeof(*parts));
296 if (parts == NULL) 296 if (parts == NULL)
297 return NULL; 297 return NULL;
298 298
299 (void)strtok(textbuf, "\n"); /* ignore first line */ 299 (void)strtok(textbuf, "\n"); /* ignore first line */
300 while ((t = strtok(NULL, "\n")) != NULL) { 300 while ((t = strtok(NULL, "\n")) != NULL) {
301 i = 0; p_start = 0; p_size = 0; p_index = 0; 301 i = 0; p_start = 0; p_size = 0; p_index = 0;
302 p_type[0] = 0; 302 p_type[0] = 0;
303 while ((tt = strsep(&t, " \t")) != NULL) { 303 while ((tt = strsep(&t, " \t")) != NULL) {
304 if (strlen(tt) == 0) 304 if (strlen(tt) == 0)
305 continue; 305 continue;
306 if (i == 0) { 306 if (i == 0) {
307 if (add_to != NULL) 307 if (add_to != NULL)
308 gpt_add_info(add_to, tt, t, false); 308 gpt_add_info(add_to, tt, t, false);
309 p_start = strtouq(tt, NULL, 10); 309 p_start = strtouq(tt, NULL, 10);
310 if (p_start == 0 && add_to != NULL) 310 if (p_start == 0 && add_to != NULL)
311 break; 311 break;
312 else 312 else
313 add_to = NULL; 313 add_to = NULL;
314 } 314 }
315 if (i == 1) 315 if (i == 1)
316 p_size = strtouq(tt, NULL, 10); 316 p_size = strtouq(tt, NULL, 10);
317 if (i == 2) 317 if (i == 2)
318 p_index = strtouq(tt, NULL, 10); 318 p_index = strtouq(tt, NULL, 10);
319 if (i > 2 || (i == 2 && p_index == 0)) { 319 if (i > 2 || (i == 2 && p_index == 0)) {
320 if (p_type[0]) 320 if (p_type[0])
321 strlcat(p_type, " ", STRSIZE); 321 strlcat(p_type, " ", STRSIZE);
322 strlcat(p_type, tt, STRSIZE); 322 strlcat(p_type, tt, STRSIZE);
323 } 323 }
324 i++; 324 i++;
325 } 325 }
326 326
327 if (p_start == 0 || p_size == 0) 327 if (p_start == 0 || p_size == 0)
328 continue; 328 continue;
329 else if (strcmp(p_type, "Pri GPT table") == 0) { 329 else if (strcmp(p_type, "Pri GPT table") == 0) {
330 avail_start = p_start + p_size; 330 avail_start = p_start + p_size;
331 parts->prologue = avail_start; 331 parts->prologue = avail_start;
332 parts->epilogue = p_size + 1; 332 parts->epilogue = p_size + 1;
333 parts->max_num_parts = p_size * GPT_PARTS_PER_SEC; 333 parts->max_num_parts = p_size * GPT_PARTS_PER_SEC;
334 } else if (strcmp(p_type, "Sec GPT table") == 0) 334 } else if (strcmp(p_type, "Sec GPT table") == 0)
335 avail_size = p_start - avail_start; 335 avail_size = p_start - avail_start;
336 else if(strcmp(p_type, "Sec GPT header") == 0) 336 else if(strcmp(p_type, "Sec GPT header") == 0)
337 disk_size = p_start + p_size; 337 disk_size = p_start + p_size;
338 else if (p_index == 0 && strlen(p_type) > 0) 338 else if (p_index == 0 && strlen(p_type) > 0)
339 /* Utilitary entry (PMBR, etc) */ 339 /* Utilitary entry (PMBR, etc) */
340 continue; 340 continue;
341 else if (p_index == 0) { 341 else if (p_index == 0) {
342 /* Free space */ 342 /* Free space */
343 continue; 343 continue;
344 } else { 344 } else {
345 /* Usual partition */ 345 /* Usual partition */
346 tt = p_type; 346 tt = p_type;
347 if (strncmp(tt, regpart_prefix, 347 if (strncmp(tt, regpart_prefix,
348 strlen(regpart_prefix)) == 0) 348 strlen(regpart_prefix)) == 0)
349 tt += strlen(regpart_prefix); 349 tt += strlen(regpart_prefix);
350 350
351 /* Add to our linked list */ 351 /* Add to our linked list */
352 struct gpt_part_entry *np = calloc(1, sizeof(*np)); 352 struct gpt_part_entry *np = calloc(1, sizeof(*np));
353 if (np == NULL) 353 if (np == NULL)
354 break; 354 break;
355 355
356 strlcpy(np->gp_label, tt, sizeof(np->gp_label)); 356 strlcpy(np->gp_label, tt, sizeof(np->gp_label));
357 np->gp_start = p_start; 357 np->gp_start = p_start;
358 np->gp_size = p_size; 358 np->gp_size = p_size;
359 np->gp_flags |= GPEF_ON_DISK; 359 np->gp_flags |= GPEF_ON_DISK;
360 if (!have_target && native_root != NULL && 360 if (!have_target && native_root != NULL &&
361 strcmp(np->gp_id, native_root->tid) == 0) { 361 strcmp(np->gp_id, native_root->tid) == 0) {
362 have_target = true; 362 have_target = true;
363 np->gp_flags |= GPEF_TARGET; 363 np->gp_flags |= GPEF_TARGET;
364 } 364 }
365 365
366 if (last == NULL) 366 if (last == NULL)
367 parts->partitions = np; 367 parts->partitions = np;
368 else 368 else
369 last->gp_next = np; 369 last->gp_next = np;
370 last = np; 370 last = np;
371 add_to = np; 371 add_to = np;
372 parts->dp.num_part++; 372 parts->dp.num_part++;
373 } 373 }
374 } 374 }
375 free(textbuf); 375 free(textbuf);
376 376
377 /* If the GPT was not complete (e.g. truncated image), barf */ 377 /* If the GPT was not complete (e.g. truncated image), barf */
378 if (disk_size <= 0) { 378 if (disk_size <= 0) {
379 free(parts); 379 free(parts);
380 return NULL; 380 return NULL;
381 } 381 }
382 382
383 parts->dp.pscheme = scheme; 383 parts->dp.pscheme = scheme;
384 parts->dp.disk = strdup(dev); 384 parts->dp.disk = strdup(dev);
385 parts->dp.disk_start = start; 385 parts->dp.disk_start = start;
386 parts->dp.disk_size = disk_size; 386 parts->dp.disk_size = disk_size;
387 parts->dp.free_space = avail_size; 387 parts->dp.free_space = avail_size;
388 parts->dp.bytes_per_sector = bps; 388 parts->dp.bytes_per_sector = bps;
389 parts->has_gpt = true; 389 parts->has_gpt = true;
390 390
391 fd = opendisk(parts->dp.disk, O_RDONLY, diskpath, sizeof(diskpath), 0); 391 fd = opendisk(parts->dp.disk, O_RDONLY, diskpath, sizeof(diskpath), 0);
392 for (struct gpt_part_entry *p = parts->partitions; p != NULL; 392 for (struct gpt_part_entry *p = parts->partitions; p != NULL;
393 p = p->gp_next) { 393 p = p->gp_next) {
394#ifdef DEFAULT_UFS2 394#ifdef DEFAULT_UFS2
395 bool fs_is_default = false; 395 bool fs_is_default = false;
396#endif 396#endif
397 397
398 if (p->gp_type != NULL) { 398 if (p->gp_type != NULL) {
399 399
400 if (p->gp_type->fsflags != 0) { 400 if (p->gp_type->fsflags != 0) {
401 const char *lm = get_last_mounted(fd, 401 const char *lm = get_last_mounted(fd,
402 p->gp_start, &p->fs_type, 402 p->gp_start, &p->fs_type,
403 &p->fs_sub_type, p->gp_type->fsflags); 403 &p->fs_sub_type, p->gp_type->fsflags);
404 if (lm != NULL && *lm != 0) { 404 if (lm != NULL && *lm != 0) {
405 char *path = strdup(lm); 405 char *path = strdup(lm);
406 canonicalize_last_mounted(path); 406 canonicalize_last_mounted(path);
407 p->last_mounted = path; 407 p->last_mounted = path;
408 } else { 408 } else {
409 p->fs_type = p->gp_type-> 409 p->fs_type = p->gp_type->
410 default_fs_type; 410 default_fs_type;
411#ifdef DEFAULT_UFS2 411#ifdef DEFAULT_UFS2
412 fs_is_default = true; 412 fs_is_default = true;
413#endif 413#endif
414 } 414 }
415 } else { 415 } else {
416 p->fs_type = p->gp_type->default_fs_type; 416 p->fs_type = p->gp_type->default_fs_type;
417#ifdef DEFAULT_UFS2 417#ifdef DEFAULT_UFS2
418 fs_is_default = true; 418 fs_is_default = true;
419#endif 419#endif
420 } 420 }
421#ifdef DEFAULT_UFS2 421#ifdef DEFAULT_UFS2
422 if (fs_is_default && p->fs_type == FS_BSDFFS) 422 if (fs_is_default && p->fs_type == FS_BSDFFS)
423 p->fs_sub_type = 2; 423 p->fs_sub_type = 2;
424#endif 424#endif
425 } 425 }
426 426
427 parts->dp.free_space -= p->gp_size; 427 parts->dp.free_space -= p->gp_size;
428 } 428 }
429 429
430 /* 430 /*
431 * Check if we have any (matching/auto-configured) wedges already 431 * Check if we have any (matching/auto-configured) wedges already
432 */ 432 */
433 dkw = NULL; 433 dkw = NULL;
434 dkwl.dkwl_buf = dkw; 434 dkwl.dkwl_buf = dkw;
435 dkwl.dkwl_bufsize = 0; 435 dkwl.dkwl_bufsize = 0;
436 if (ioctl(fd, DIOCLWEDGES, &dkwl) == 0) { 436 if (ioctl(fd, DIOCLWEDGES, &dkwl) == 0) {
437 /* do not even try to deal with any races at this point */ 437 /* do not even try to deal with any races at this point */
438 bufsize = dkwl.dkwl_nwedges * sizeof(*dkw); 438 bufsize = dkwl.dkwl_nwedges * sizeof(*dkw);
439 dkw = malloc(bufsize); 439 dkw = malloc(bufsize);
440 dkwl.dkwl_buf = dkw; 440 dkwl.dkwl_buf = dkw;
441 dkwl.dkwl_bufsize = bufsize; 441 dkwl.dkwl_bufsize = bufsize;
442 if (dkw != NULL && ioctl(fd, DIOCLWEDGES, &dkwl) == 0) { 442 if (dkw != NULL && ioctl(fd, DIOCLWEDGES, &dkwl) == 0) {
443 for (dk = 0; dk < dkwl.dkwl_ncopied; dk++) 443 for (dk = 0; dk < dkwl.dkwl_ncopied; dk++)
444 update_part_from_wedge_info(parts, &dkw[dk]); 444 update_part_from_wedge_info(parts, &dkw[dk]);
445 } 445 }
446 free(dkw); 446 free(dkw);
447 } 447 }
448 448
449 close(fd); 449 close(fd);
450 450
451 return &parts->dp; 451 return &parts->dp;
452} 452}
453 453
454static size_t 454static size_t
455gpt_cyl_size(const struct disk_partitions *arg) 455gpt_cyl_size(const struct disk_partitions *arg)
456{ 456{
457 return MEG / 512; 457 return MEG / 512;
458} 458}
459 459
460static struct disk_partitions * 460static struct disk_partitions *
461gpt_create_new(const char *disk, daddr_t start, daddr_t len, 461gpt_create_new(const char *disk, daddr_t start, daddr_t len,
462 bool is_boot_drive, struct disk_partitions *parent) 462 bool is_boot_drive, struct disk_partitions *parent)
463{ 463{
464 struct gpt_disk_partitions *parts; 464 struct gpt_disk_partitions *parts;
465 struct disk_geom geo; 465 struct disk_geom geo;
466 466
467 if (start != 0) { 467 if (start != 0) {
468 assert(0); 468 assert(0);
469 return NULL; 469 return NULL;
470 } 470 }
471 471
472 if (!get_disk_geom(disk, &geo)) 472 if (!get_disk_geom(disk, &geo))
473 return NULL; 473 return NULL;
474 474
475 parts = calloc(1, sizeof(*parts)); 475 parts = calloc(1, sizeof(*parts));
476 if (!parts) 476 if (!parts)
477 return NULL; 477 return NULL;
478 478
479 parts->dp.pscheme = &gpt_parts; 479 parts->dp.pscheme = &gpt_parts;
480 parts->dp.disk = strdup(disk); 480 parts->dp.disk = strdup(disk);
481 481
482 gpt_md_init(is_boot_drive, &parts->max_num_parts, &parts->prologue, 482 gpt_md_init(is_boot_drive, &parts->max_num_parts, &parts->prologue,
483 &parts->epilogue); 483 &parts->epilogue);
484 484
485 parts->dp.disk_start = start; 485 parts->dp.disk_start = start;
486 parts->dp.disk_size = len; 486 parts->dp.disk_size = len;
487 parts->dp.bytes_per_sector = geo.dg_secsize; 487 parts->dp.bytes_per_sector = geo.dg_secsize;
488 parts->dp.free_space = len - start - parts->prologue - parts->epilogue; 488 parts->dp.free_space = len - start - parts->prologue - parts->epilogue;
489 parts->has_gpt = false; 489 parts->has_gpt = false;
490 490
491 return &parts->dp; 491 return &parts->dp;
492} 492}
493 493
494static bool 494static bool
495gpt_get_part_info(const struct disk_partitions *arg, part_id id, 495gpt_get_part_info(const struct disk_partitions *arg, part_id id,
496 struct disk_part_info *info) 496 struct disk_part_info *info)
497{ 497{
498 static const struct part_type_desc gpt_unknown_type = 498 static const struct part_type_desc gpt_unknown_type =
499 { .generic_ptype = PT_undef, 499 { .generic_ptype = PT_undef,
500 .short_desc = "<unknown>" }; 500 .short_desc = "<unknown>" };
501 const struct gpt_disk_partitions *parts = 501 const struct gpt_disk_partitions *parts =
502 (const struct gpt_disk_partitions*)arg; 502 (const struct gpt_disk_partitions*)arg;
503 const struct gpt_part_entry *p = parts->partitions; 503 const struct gpt_part_entry *p = parts->partitions;
504 part_id no; 504 part_id no;
505 505
506 for (no = 0; p != NULL && no < id; no++) 506 for (no = 0; p != NULL && no < id; no++)
507 p = p->gp_next; 507 p = p->gp_next;
508 508
509 if (no != id || p == NULL) 509 if (no != id || p == NULL)
510 return false; 510 return false;
511 511
512 memset(info, 0, sizeof(*info)); 512 memset(info, 0, sizeof(*info));
513 info->start = p->gp_start; 513 info->start = p->gp_start;
514 info->size = p->gp_size; 514 info->size = p->gp_size;
515 if (p->gp_type) 515 if (p->gp_type)
516 info->nat_type = &p->gp_type->gent; 516 info->nat_type = &p->gp_type->gent;
517 else 517 else
518 info->nat_type = &gpt_unknown_type; 518 info->nat_type = &gpt_unknown_type;
519 info->last_mounted = p->last_mounted; 519 info->last_mounted = p->last_mounted;
520 info->fs_type = p->fs_type; 520 info->fs_type = p->fs_type;
521 info->fs_sub_type = p->fs_sub_type; 521 info->fs_sub_type = p->fs_sub_type;
522 info->fs_opt1 = p->fs_opt1; 522 info->fs_opt1 = p->fs_opt1;
523 info->fs_opt2 = p->fs_opt2; 523 info->fs_opt2 = p->fs_opt2;
524 info->fs_opt3 = p->fs_opt3; 524 info->fs_opt3 = p->fs_opt3;
525 if (p->gp_flags & GPEF_TARGET) 525 if (p->gp_flags & GPEF_TARGET)
526 info->flags |= PTI_INSTALL_TARGET; 526 info->flags |= PTI_INSTALL_TARGET;
527 527
528 return true; 528 return true;
529} 529}
530 530
531static bool 531static bool
532gpt_get_part_attr_str(const struct disk_partitions *arg, part_id id, 532gpt_get_part_attr_str(const struct disk_partitions *arg, part_id id,
533 char *str, size_t avail_space) 533 char *str, size_t avail_space)
534{ 534{
535 const struct gpt_disk_partitions *parts = 535 const struct gpt_disk_partitions *parts =
536 (const struct gpt_disk_partitions*)arg; 536 (const struct gpt_disk_partitions*)arg;
537 const struct gpt_part_entry *p = parts->partitions; 537 const struct gpt_part_entry *p = parts->partitions;
538 part_id no; 538 part_id no;
539 static const char *flags = NULL; 539 static const char *flags = NULL;
540 540
541 for (no = 0; p != NULL && no < id; no++) 541 for (no = 0; p != NULL && no < id; no++)
542 p = p->gp_next; 542 p = p->gp_next;
543 543
544 if (no != id || p == NULL) 544 if (no != id || p == NULL)
545 return false; 545 return false;
546 546
547 if (flags == NULL) 547 if (flags == NULL)
548 flags = msg_string(MSG_gpt_flags); 548 flags = msg_string(MSG_gpt_flags);
549 549
550 if (avail_space < 2) 550 if (avail_space < 2)
551 return false; 551 return false;
552 552
553 if (p->gp_attr & GPT_ATTR_BOOT) 553 if (p->gp_attr & GPT_ATTR_BOOT)
554 *str++ = flags[0]; 554 *str++ = flags[0];
555 *str = 0; 555 *str = 0;
556 556
557 return true; 557 return true;
558} 558}
559 559
560/* 560/*
561 * Find insert position and check for duplicates. 561 * Find insert position and check for duplicates.
562 * If all goes well, insert the new "entry" in the "list". 562 * If all goes well, insert the new "entry" in the "list".
563 * If there are collisions, report "no free space". 563 * If there are collisions, report "no free space".
564 * We keep all lists sorted by start sector number, 564 * We keep all lists sorted by start sector number,
565 */ 565 */
566static bool 566static bool
567gpt_insert_part_into_list(struct gpt_disk_partitions *parts, 567gpt_insert_part_into_list(struct gpt_disk_partitions *parts,
568 struct gpt_part_entry **list, 568 struct gpt_part_entry **list,
569 struct gpt_part_entry *entry, const char **err_msg) 569 struct gpt_part_entry *entry, const char **err_msg)
570{ 570{
571 struct gpt_part_entry *p, *last; 571 struct gpt_part_entry *p, *last;
572 572
573 /* find the first entry past the new one (if any) */ 573 /* find the first entry past the new one (if any) */
574 for (last = NULL, p = *list; p != NULL; last = p, p = p->gp_next) { 574 for (last = NULL, p = *list; p != NULL; last = p, p = p->gp_next) {
575 if (p->gp_start > entry->gp_start) 575 if (p->gp_start > entry->gp_start)
576 break; 576 break;
577 } 577 }
578 578
579 /* check if last partition overlaps with new one */ 579 /* check if last partition overlaps with new one */
580 if (last) { 580 if (last) {
581 if (last->gp_start + last->gp_size > entry->gp_start) { 581 if (last->gp_start + last->gp_size > entry->gp_start) {
582 if (err_msg) 582 if (err_msg)
583 *err_msg = msg_string(MSG_No_free_space); 583 *err_msg = msg_string(MSG_No_free_space);
584 return false; 584 return false;
585 } 585 }
586 } 586 }
587 587
588 if (p == NULL) { 588 if (p == NULL) {
589 entry->gp_next = NULL; 589 entry->gp_next = NULL;
590 if (last != NULL) { 590 if (last != NULL) {
591 last->gp_next = entry; 591 last->gp_next = entry;
592 } 592 }
593 } else { 593 } else {
594 /* check if new entry overlaps with next */ 594 /* check if new entry overlaps with next */
595 if (entry->gp_start + entry->gp_size > p->gp_start) { 595 if (entry->gp_start + entry->gp_size > p->gp_start) {
596 if (err_msg) 596 if (err_msg)
597 *err_msg = msg_string(MSG_No_free_space); 597 *err_msg = msg_string(MSG_No_free_space);
598 return false; 598 return false;
599 } 599 }
600 600
601 entry->gp_next = p; 601 entry->gp_next = p;
602 if (last != NULL) 602 if (last != NULL)
603 last->gp_next = entry; 603 last->gp_next = entry;
604 else 604 else
605 *list = entry; 605 *list = entry;
606 } 606 }
607 if (*list == NULL) 607 if (*list == NULL)
608 *list = entry; 608 *list = entry;
609 609
610 return true; 610 return true;
611} 611}
612 612
613static bool 613static bool
614gpt_set_part_info(struct disk_partitions *arg, part_id id, 614gpt_set_part_info(struct disk_partitions *arg, part_id id,
615 const struct disk_part_info *info, const char **err_msg) 615 const struct disk_part_info *info, const char **err_msg)
616{ 616{
617 struct gpt_disk_partitions *parts = 617 struct gpt_disk_partitions *parts =
618 (struct gpt_disk_partitions*)arg; 618 (struct gpt_disk_partitions*)arg;
619 struct gpt_part_entry *p = parts->partitions, *n; 619 struct gpt_part_entry *p = parts->partitions, *n;
620 part_id no; 620 part_id no;
621 daddr_t lendiff; 621 daddr_t lendiff;
622 bool was_target; 622 bool was_target;
623 623
624 for (no = 0; p != NULL && no < id; no++) 624 for (no = 0; p != NULL && no < id; no++)
625 p = p->gp_next; 625 p = p->gp_next;
626 626
627 if (no != id || p == NULL) 627 if (no != id || p == NULL)
628 return false; 628 return false;
629 629
630 /* update target mark - we can only have one */ 630 /* update target mark - we can only have one */
631 was_target = (p->gp_flags & GPEF_TARGET) != 0; 631 was_target = (p->gp_flags & GPEF_TARGET) != 0;
632 if (info->flags & PTI_INSTALL_TARGET) 632 if (info->flags & PTI_INSTALL_TARGET)
633 p->gp_flags |= GPEF_TARGET; 633 p->gp_flags |= GPEF_TARGET;
634 else 634 else
635 p->gp_flags &= ~GPEF_TARGET; 635 p->gp_flags &= ~GPEF_TARGET;
636 if (was_target) 636 if (was_target)
637 for (n = parts->partitions; n != NULL; n = n->gp_next) 637 for (n = parts->partitions; n != NULL; n = n->gp_next)
638 if (n != p) 638 if (n != p)
639 n->gp_flags &= ~GPEF_TARGET; 639 n->gp_flags &= ~GPEF_TARGET;
640 640
641 if ((p->gp_flags & GPEF_ON_DISK)) { 641 if ((p->gp_flags & GPEF_ON_DISK)) {
642 if (info->start != p->gp_start) { 642 if (info->start != p->gp_start) {
643 /* partition moved, we need to delete and re-add */ 643 /* partition moved, we need to delete and re-add */
644 n = calloc(1, sizeof(*n)); 644 n = calloc(1, sizeof(*n));
645 if (n == NULL) { 645 if (n == NULL) {
646 if (err_msg) 646 if (err_msg)
647 *err_msg = err_outofmem; 647 *err_msg = err_outofmem;
648 return false; 648 return false;
649 } 649 }
650 *n = *p; 650 *n = *p;
651 p->gp_flags &= ~GPEF_ON_DISK; 651 p->gp_flags &= ~GPEF_ON_DISK;
652 if (!gpt_insert_part_into_list(parts, &parts->obsolete, 652 if (!gpt_insert_part_into_list(parts, &parts->obsolete,
653 n, err_msg)) 653 n, err_msg))
654 return false; 654 return false;
655 } else if (info->size != p->gp_size) { 655 } else if (info->size != p->gp_size) {
656 p->gp_flags |= GPEF_RESIZED; 656 p->gp_flags |= GPEF_RESIZED;
657 } 657 }
658 } 658 }
659 659
660 p->gp_flags |= GPEF_MODIFIED; 660 p->gp_flags |= GPEF_MODIFIED;
661 661
662 lendiff = info->size - p->gp_size; 662 lendiff = info->size - p->gp_size;
663 parts->dp.free_space -= lendiff; 663 parts->dp.free_space -= lendiff;
664 return gpt_info_to_part(p, info, err_msg); 664 return gpt_info_to_part(p, info, err_msg);
665} 665}
666 666
667static size_t 667static size_t
668gpt_get_free_spaces_internal(const struct gpt_disk_partitions *parts, 668gpt_get_free_spaces_internal(const struct gpt_disk_partitions *parts,
669 struct disk_part_free_space *result, size_t max_num_result, 669 struct disk_part_free_space *result, size_t max_num_result,
670 daddr_t min_space_size, daddr_t align, daddr_t start, daddr_t ignore) 670 daddr_t min_space_size, daddr_t align, daddr_t start, daddr_t ignore)
671{ 671{
672 size_t cnt = 0; 672 size_t cnt = 0;
673 daddr_t s, e, from, size, end_of_disk; 673 daddr_t s, e, from, size, end_of_disk;
674 struct gpt_part_entry *p; 674 struct gpt_part_entry *p;
675 675
676 if (align > 1) 676 if (align > 1)
677 start = max(roundup(start, align), align); 677 start = max(roundup(start, align), align);
678 if (start < 0 || start < (daddr_t)parts->prologue) 678 if (start < 0 || start < (daddr_t)parts->prologue)
679 start = parts->prologue; 679 start = parts->prologue;
680 if (parts->dp.disk_start != 0 && parts->dp.disk_start > start) 680 if (parts->dp.disk_start != 0 && parts->dp.disk_start > start)
681 start = parts->dp.disk_start; 681 start = parts->dp.disk_start;
682 if (min_space_size < 1) 682 if (min_space_size < 1)
683 min_space_size = 1; 683 min_space_size = 1;
684 end_of_disk = parts->dp.disk_start + parts->dp.disk_size 684 end_of_disk = parts->dp.disk_start + parts->dp.disk_size
685 - parts->epilogue; 685 - parts->epilogue;
686 from = start; 686 from = start;
687 while (from < end_of_disk && cnt < max_num_result) { 687 while (from < end_of_disk && cnt < max_num_result) {
688again: 688again:
689 size = parts->dp.disk_start + parts->dp.disk_size - from; 689 size = parts->dp.disk_start + parts->dp.disk_size - from;
690 start = from; 690 start = from;
691 if (start + size > end_of_disk) 691 if (start + size > end_of_disk)
692 size = end_of_disk - start; 692 size = end_of_disk - start;
693 for (p = parts->partitions; p != NULL; p = p->gp_next) { 693 for (p = parts->partitions; p != NULL; p = p->gp_next) {
694 s = p->gp_start; 694 s = p->gp_start;
695 e = p->gp_size + s; 695 e = p->gp_size + s;
696 if (s == ignore) 696 if (s == ignore)
697 continue; 697 continue;
698 if (e < from) 698 if (e < from)
699 continue; 699 continue;
700 if (s <= from && e > from) { 700 if (s <= from && e > from) {
701 if (e - 1 >= end_of_disk) 701 if (e - 1 >= end_of_disk)
702 return cnt; 702 return cnt;
703 from = e + 1; 703 from = e + 1;
704 if (align > 1) { 704 if (align > 1) {
705 from = max(roundup(from, align), align); 705 from = max(roundup(from, align), align);
706 if (from >= end_of_disk) { 706 if (from >= end_of_disk) {
707 size = 0; 707 size = 0;
708 break; 708 break;
709 } 709 }
710 } 710 }
711 goto again; 711 goto again;
712 } 712 }
713 if (s > from && s - from < size) { 713 if (s > from && s - from < size) {
714 size = s - from; 714 size = s - from;
715 } 715 }
716 } 716 }
717 if (size >= min_space_size) { 717 if (size >= min_space_size) {
718 result->start = start; 718 result->start = start;
719 result->size = size; 719 result->size = size;
720 result++; 720 result++;
721 cnt++; 721 cnt++;
722 } 722 }
723 from += size + 1; 723 from += size + 1;
724 if (align > 1) 724 if (align > 1)
725 from = max(roundup(from, align), align); 725 from = max(roundup(from, align), align);
726 } 726 }
727 727
728 return cnt; 728 return cnt;
729} 729}
730 730
731static daddr_t 731static daddr_t
732gpt_max_free_space_at(const struct disk_partitions *arg, daddr_t start) 732gpt_max_free_space_at(const struct disk_partitions *arg, daddr_t start)
733{ 733{
734 const struct gpt_disk_partitions *parts = 734 const struct gpt_disk_partitions *parts =
735 (const struct gpt_disk_partitions*)arg; 735 (const struct gpt_disk_partitions*)arg;
736 struct disk_part_free_space space; 736 struct disk_part_free_space space;
737 737
738 if (gpt_get_free_spaces_internal(parts, &space, 1, 1, 0, 738 if (gpt_get_free_spaces_internal(parts, &space, 1, 1, 0,
739 start, start) == 1) 739 start, start) == 1)
740 return space.size; 740 return space.size;
741 741
742 return 0; 742 return 0;
743} 743}
744 744
745static size_t 745static size_t
746gpt_get_free_spaces(const struct disk_partitions *arg, 746gpt_get_free_spaces(const struct disk_partitions *arg,
747 struct disk_part_free_space *result, size_t max_num_result, 747 struct disk_part_free_space *result, size_t max_num_result,
748 daddr_t min_space_size, daddr_t align, daddr_t start, 748 daddr_t min_space_size, daddr_t align, daddr_t start,
749 daddr_t ignore) 749 daddr_t ignore)
750{ 750{
751 const struct gpt_disk_partitions *parts = 751 const struct gpt_disk_partitions *parts =
752 (const struct gpt_disk_partitions*)arg; 752 (const struct gpt_disk_partitions*)arg;
753 753
754 return gpt_get_free_spaces_internal(parts, result, 754 return gpt_get_free_spaces_internal(parts, result,
755 max_num_result, min_space_size, align, start, ignore); 755 max_num_result, min_space_size, align, start, ignore);
756} 756}
757 757
758static void 758static void
759gpt_match_ptype(const char *name, struct gpt_ptype_desc *t) 759gpt_match_ptype(const char *name, struct gpt_ptype_desc *t)
760{ 760{
761 size_t i; 761 size_t i;
762 762
763 for (i = 0; i < __arraycount(gpt_fs_types); i++) { 763 for (i = 0; i < __arraycount(gpt_fs_types); i++) {
764 if (strcmp(name, gpt_fs_types[i].name) == 0) { 764 if (strcmp(name, gpt_fs_types[i].name) == 0) {
765 t->gent.generic_ptype = gpt_fs_types[i].ptype; 765 t->gent.generic_ptype = gpt_fs_types[i].ptype;
766 t->fsflags = gpt_fs_types[i].fsflags; 766 t->fsflags = gpt_fs_types[i].fsflags;
767 t->default_fs_type = gpt_fs_types[i].fstype; 767 t->default_fs_type = gpt_fs_types[i].fstype;
768 768
769 /* recongnize special entries */ 769 /* recongnize special entries */
770 if (gpt_native_root == NULL && i == 0) 770 if (gpt_native_root == NULL && i == 0)
771 gpt_native_root = &t->gent; 771 gpt_native_root = &t->gent;
772 772
773 return; 773 return;
774 } 774 }
775 } 775 }
776 776
777 t->gent.generic_ptype = PT_unknown; 777 t->gent.generic_ptype = PT_unknown;
778 t->fsflags = 0; 778 t->fsflags = 0;
779 t->default_fs_type = FS_BSDFFS; 779 t->default_fs_type = FS_BSDFFS;
780} 780}
781 781
782static void 782static void
783gpt_internal_add_ptype(const char *uid, const char *name, const char *desc) 783gpt_internal_add_ptype(const char *uid, const char *name, const char *desc)
784{ 784{
785 if (gpt_ptype_cnt >= gpt_ptype_alloc) { 785 if (gpt_ptype_cnt >= gpt_ptype_alloc) {
786 gpt_ptype_alloc = gpt_ptype_alloc ? 2*gpt_ptype_alloc 786 gpt_ptype_alloc = gpt_ptype_alloc ? 2*gpt_ptype_alloc
787 : GPT_PTYPE_ALLOC; 787 : GPT_PTYPE_ALLOC;
788 struct gpt_ptype_desc *nptypes = realloc(gpt_ptype_descs, 788 struct gpt_ptype_desc *nptypes = realloc(gpt_ptype_descs,
789 gpt_ptype_alloc*sizeof(*gpt_ptype_descs)); 789 gpt_ptype_alloc*sizeof(*gpt_ptype_descs));
790 if (nptypes == 0) 790 if (nptypes == 0)
791 errx(EXIT_FAILURE, "out of memory"); 791 errx(EXIT_FAILURE, "out of memory");
792 gpt_ptype_descs = nptypes; 792 gpt_ptype_descs = nptypes;
793 } 793 }
794 794
795 strlcpy(gpt_ptype_descs[gpt_ptype_cnt].tid, uid, 795 strlcpy(gpt_ptype_descs[gpt_ptype_cnt].tid, uid,
796 sizeof(gpt_ptype_descs[gpt_ptype_cnt].tid)); 796 sizeof(gpt_ptype_descs[gpt_ptype_cnt].tid));
797 gpt_ptype_descs[gpt_ptype_cnt].gent.short_desc = strdup(name); 797 gpt_ptype_descs[gpt_ptype_cnt].gent.short_desc = strdup(name);
798 gpt_ptype_descs[gpt_ptype_cnt].gent.description = strdup(desc); 798 gpt_ptype_descs[gpt_ptype_cnt].gent.description = strdup(desc);
799 gpt_match_ptype(name, &gpt_ptype_descs[gpt_ptype_cnt]); 799 gpt_match_ptype(name, &gpt_ptype_descs[gpt_ptype_cnt]);
800 gpt_ptype_cnt++; 800 gpt_ptype_cnt++;
801} 801}
802 802
803static void 803static void
804gpt_init_ptypes(void) 804gpt_init_ptypes(void)
805{ 805{
806 if (gpt_ptype_cnt == 0) 806 if (gpt_ptype_cnt == 0)
807 gpt_uuid_query(gpt_internal_add_ptype); 807 gpt_uuid_query(gpt_internal_add_ptype);
808} 808}
809 809
810static void 810static void
811gpt_cleanup(void) 811gpt_cleanup(void)
812{ 812{
813 /* free all of gpt_ptype_descs */ 813 /* free all of gpt_ptype_descs */
814 for (size_t i = 0; i < gpt_ptype_cnt; i++) { 814 for (size_t i = 0; i < gpt_ptype_cnt; i++) {
815 free(__UNCONST(gpt_ptype_descs[i].gent.short_desc)); 815 free(__UNCONST(gpt_ptype_descs[i].gent.short_desc));
816 free(__UNCONST(gpt_ptype_descs[i].gent.description)); 816 free(__UNCONST(gpt_ptype_descs[i].gent.description));
817 } 817 }
818 free(gpt_ptype_descs); 818 free(gpt_ptype_descs);
819 gpt_ptype_descs = NULL; 819 gpt_ptype_descs = NULL;
820 gpt_ptype_cnt = gpt_ptype_alloc = 0; 820 gpt_ptype_cnt = gpt_ptype_alloc = 0;
821} 821}
822 822
823static size_t 823static size_t
824gpt_type_count(void) 824gpt_type_count(void)
825{ 825{
826 if (gpt_ptype_cnt == 0) 826 if (gpt_ptype_cnt == 0)
827 gpt_init_ptypes(); 827 gpt_init_ptypes();
828 828
829 return gpt_ptype_cnt; 829 return gpt_ptype_cnt;
830} 830}
831 831
832static const struct part_type_desc * 832static const struct part_type_desc *
833gpt_get_ptype(size_t ndx) 833gpt_get_ptype(size_t ndx)
834{ 834{
835 if (gpt_ptype_cnt == 0) 835 if (gpt_ptype_cnt == 0)
836 gpt_init_ptypes(); 836 gpt_init_ptypes();
837 837
838 if (ndx >= gpt_ptype_cnt) 838 if (ndx >= gpt_ptype_cnt)
839 return NULL; 839 return NULL;
840 840
841 return &gpt_ptype_descs[ndx].gent; 841 return &gpt_ptype_descs[ndx].gent;
842} 842}
843 843
844static const struct part_type_desc * 844static const struct part_type_desc *
845gpt_get_generic_type(enum part_type gent) 845gpt_get_generic_type(enum part_type gent)
846{ 846{
847 if (gpt_ptype_cnt == 0) 847 if (gpt_ptype_cnt == 0)
848 gpt_init_ptypes(); 848 gpt_init_ptypes();
849 849
850 if (gent == PT_root) 850 if (gent == PT_root)
851 return gpt_native_root; 851 return gpt_native_root;
852 if (gent == PT_unknown) 852 if (gent == PT_unknown)
853 return NULL; 853 return NULL;
854 854
855 for (size_t i = 0; i < gpt_ptype_cnt; i++) 855 for (size_t i = 0; i < gpt_ptype_cnt; i++)
856 if (gpt_ptype_descs[i].gent.generic_ptype == gent) 856 if (gpt_ptype_descs[i].gent.generic_ptype == gent)
857 return &gpt_ptype_descs[i].gent; 857 return &gpt_ptype_descs[i].gent;
858 858
859 return NULL; 859 return NULL;
860} 860}
861 861
862static const struct gpt_ptype_desc * 862static const struct gpt_ptype_desc *
863gpt_find_native_type(const struct part_type_desc *gent) 863gpt_find_native_type(const struct part_type_desc *gent)
864{ 864{
865 if (gpt_ptype_cnt == 0) 865 if (gpt_ptype_cnt == 0)
866 gpt_init_ptypes(); 866 gpt_init_ptypes();
867 867
868 if (gent == NULL) 868 if (gent == NULL)
869 return NULL; 869 return NULL;
870 870
871 for (size_t i = 0; i < gpt_ptype_cnt; i++) 871 for (size_t i = 0; i < gpt_ptype_cnt; i++)
872 if (gent == &gpt_ptype_descs[i].gent) 872 if (gent == &gpt_ptype_descs[i].gent)
873 return &gpt_ptype_descs[i]; 873 return &gpt_ptype_descs[i];
874 874
875 gent = gpt_get_generic_type(gent->generic_ptype); 875 gent = gpt_get_generic_type(gent->generic_ptype);
876 if (gent == NULL) 876 if (gent == NULL)
877 return NULL; 877 return NULL;
878 878
879 /* this can not recurse deeper than once, we would not have found a 879 /* this can not recurse deeper than once, we would not have found a
880 * generic type a few lines above if it would. */ 880 * generic type a few lines above if it would. */
881 return gpt_find_native_type(gent); 881 return gpt_find_native_type(gent);
882} 882}
883 883
884static const struct gpt_ptype_desc * 884static const struct gpt_ptype_desc *
885gpt_find_guid_type(const char *uid) 885gpt_find_guid_type(const char *uid)
886{ 886{
887 if (gpt_ptype_cnt == 0) 887 if (gpt_ptype_cnt == 0)
888 gpt_init_ptypes(); 888 gpt_init_ptypes();
889 889
890 if (uid == NULL || uid[0] == 0) 890 if (uid == NULL || uid[0] == 0)
891 return NULL; 891 return NULL;
892 892
893 for (size_t i = 0; i < gpt_ptype_cnt; i++) 893 for (size_t i = 0; i < gpt_ptype_cnt; i++)
894 if (strcmp(gpt_ptype_descs[i].tid, uid) == 0) 894 if (strcmp(gpt_ptype_descs[i].tid, uid) == 0)
895 return &gpt_ptype_descs[i]; 895 return &gpt_ptype_descs[i];
896 896
897 return NULL; 897 return NULL;
898} 898}
899 899
900static const struct part_type_desc * 900static const struct part_type_desc *
901gpt_find_type(const char *desc) 901gpt_find_type(const char *desc)
902{ 902{
903 if (gpt_ptype_cnt == 0) 903 if (gpt_ptype_cnt == 0)
904 gpt_init_ptypes(); 904 gpt_init_ptypes();
905 905
906 if (desc == NULL || desc[0] == 0) 906 if (desc == NULL || desc[0] == 0)
907 return NULL; 907 return NULL;
908 908
909 for (size_t i = 0; i < gpt_ptype_cnt; i++) 909 for (size_t i = 0; i < gpt_ptype_cnt; i++)
910 if (strcmp(gpt_ptype_descs[i].gent.short_desc, desc) == 0) 910 if (strcmp(gpt_ptype_descs[i].gent.short_desc, desc) == 0)
911 return &gpt_ptype_descs[i].gent; 911 return &gpt_ptype_descs[i].gent;
912 912
913 return NULL; 913 return NULL;
914} 914}
915 915
916static const struct part_type_desc * 916static const struct part_type_desc *
917gpt_get_fs_part_type(enum part_type pt, unsigned fstype, unsigned fs_sub_type) 917gpt_get_fs_part_type(enum part_type pt, unsigned fstype, unsigned fs_sub_type)
918{ 918{
919 size_t i; 919 size_t i;
920 920
921 /* Try with complete match (including part_type) first */ 921 /* Try with complete match (including part_type) first */
922 for (i = 0; i < __arraycount(gpt_fs_types); i++) 922 for (i = 0; i < __arraycount(gpt_fs_types); i++)
923 if (fstype == gpt_fs_types[i].fstype && 923 if (fstype == gpt_fs_types[i].fstype &&
924 pt == gpt_fs_types[i].ptype) 924 pt == gpt_fs_types[i].ptype)
925 return gpt_find_type(gpt_fs_types[i].name); 925 return gpt_find_type(gpt_fs_types[i].name);
926 926
927 /* If that did not work, ignore part_type */ 927 /* If that did not work, ignore part_type */
928 for (i = 0; i < __arraycount(gpt_fs_types); i++) 928 for (i = 0; i < __arraycount(gpt_fs_types); i++)
929 if (fstype == gpt_fs_types[i].fstype) 929 if (fstype == gpt_fs_types[i].fstype)
930 return gpt_find_type(gpt_fs_types[i].name); 930 return gpt_find_type(gpt_fs_types[i].name);
931 931
932 return NULL; 932 return NULL;
933} 933}
934 934
935static bool 935static bool
936gpt_get_default_fstype(const struct part_type_desc *nat_type, 936gpt_get_default_fstype(const struct part_type_desc *nat_type,
937 unsigned *fstype, unsigned *fs_sub_type) 937 unsigned *fstype, unsigned *fs_sub_type)
938{ 938{
939 const struct gpt_ptype_desc *gtype; 939 const struct gpt_ptype_desc *gtype;
940 940
941 gtype = gpt_find_native_type(nat_type); 941 gtype = gpt_find_native_type(nat_type);
942 if (gtype == NULL) 942 if (gtype == NULL)
943 return false; 943 return false;
944 944
945 *fstype = gtype->default_fs_type; 945 *fstype = gtype->default_fs_type;
946#ifdef DEFAULT_UFS2 946#ifdef DEFAULT_UFS2
947 if (gtype->default_fs_type == FS_BSDFFS) 947 if (gtype->default_fs_type == FS_BSDFFS)
948 *fs_sub_type = 2; 948 *fs_sub_type = 2;
949 else 949 else
950#endif 950#endif
951 *fs_sub_type = 0; 951 *fs_sub_type = 0;
952 return true; 952 return true;
953} 953}
954 954
955static const struct part_type_desc * 955static const struct part_type_desc *
956gpt_get_uuid_part_type(const uuid_t *id) 956gpt_get_uuid_part_type(const uuid_t *id)
957{ 957{
958 char str[GUID_STR_LEN], desc[GUID_STR_LEN + MENUSTRSIZE]; 958 char str[GUID_STR_LEN], desc[GUID_STR_LEN + MENUSTRSIZE];
959 const struct gpt_ptype_desc *t; 959 const struct gpt_ptype_desc *t;
960 char *guid = NULL; 960 char *guid = NULL;
961 uint32_t err; 961 uint32_t err;
962 962
963 uuid_to_string(id, &guid, &err); 963 uuid_to_string(id, &guid, &err);
964 strlcpy(str, err == uuid_s_ok ? guid : "-", sizeof str); 964 strlcpy(str, err == uuid_s_ok ? guid : "-", sizeof str);
965 free(guid); 965 free(guid);
966 966
967 t = gpt_find_guid_type(str); 967 t = gpt_find_guid_type(str);
968 if (t == NULL) { 968 if (t == NULL) {
969 snprintf(desc, sizeof desc, "%s (%s)", 969 snprintf(desc, sizeof desc, "%s (%s)",
970 msg_string(MSG_custom_type), str); 970 msg_string(MSG_custom_type), str);
971 gpt_internal_add_ptype(str, str, desc); 971 gpt_internal_add_ptype(str, str, desc);
972 t = gpt_find_guid_type(str); 972 t = gpt_find_guid_type(str);
973 assert(t != NULL); 973 assert(t != NULL);
974 } 974 }
975 return &t->gent; 975 return &t->gent;
976} 976}
977 977
978static const struct part_type_desc * 978static const struct part_type_desc *
979gpt_create_custom_part_type(const char *custom, const char **err_msg) 979gpt_create_custom_part_type(const char *custom, const char **err_msg)
980{ 980{
981 uuid_t id; 981 uuid_t id;
982 uint32_t err; 982 uint32_t err;
983 983
984 uuid_from_string(custom, &id, &err); 984 uuid_from_string(custom, &id, &err);
985 if (err_msg != NULL && 985 if (err_msg != NULL &&
986 (err == uuid_s_invalid_string_uuid || err == uuid_s_bad_version)) { 986 (err == uuid_s_invalid_string_uuid || err == uuid_s_bad_version)) {
987 *err_msg = MSG_invalid_guid; 987 *err_msg = MSG_invalid_guid;
988 return NULL; 988 return NULL;
989 } 989 }
990 if (err != uuid_s_ok) 990 if (err != uuid_s_ok)
991 return NULL; 991 return NULL;
992 992
993 return gpt_get_uuid_part_type(&id); 993 return gpt_get_uuid_part_type(&id);
994} 994}
995 995
996static const struct part_type_desc * 996static const struct part_type_desc *
997gpt_create_unknown_part_type(void) 997gpt_create_unknown_part_type(void)
998{ 998{
999 uuid_t id; 999 uuid_t id;
1000 uint32_t err; 1000 uint32_t err;
1001 1001
1002 uuid_create(&id, &err); 1002 uuid_create(&id, &err);
1003 if (err != uuid_s_ok) 1003 if (err != uuid_s_ok)
1004 return NULL; 1004 return NULL;
1005 1005
1006 return gpt_get_uuid_part_type(&id); 1006 return gpt_get_uuid_part_type(&id);
1007} 1007}
1008 1008
1009static daddr_t 1009static daddr_t
1010gpt_get_part_alignment(const struct disk_partitions *parts) 1010gpt_get_part_alignment(const struct disk_partitions *parts)
1011{ 1011{
1012 1012
1013 assert(parts->disk_size > 0); 1013 assert(parts->disk_size > 0);
1014 if (parts->disk_size < 0) 1014 if (parts->disk_size < 0)
1015 return 1; 1015 return 1;
1016 1016
1017 /* Use 1MB offset/alignemnt for large (>128GB) disks */ 1017 /* Use 1MB offset/alignemnt for large (>128GB) disks */
1018 if (parts->disk_size > HUGE_DISK_SIZE) 1018 if (parts->disk_size > HUGE_DISK_SIZE)
1019 return 2048; 1019 return 2048;
1020 else if (parts->disk_size > TINY_DISK_SIZE) 1020 else if (parts->disk_size > TINY_DISK_SIZE)
1021 return 64; 1021 return 64;
1022 else 1022 else
1023 return 4; 1023 return 4;
1024} 1024}
1025 1025
1026static bool 1026static bool
1027gpt_can_add_partition(const struct disk_partitions *arg) 1027gpt_can_add_partition(const struct disk_partitions *arg)
1028{ 1028{
1029 const struct gpt_disk_partitions *parts = 1029 const struct gpt_disk_partitions *parts =
1030 (const struct gpt_disk_partitions*)arg; 1030 (const struct gpt_disk_partitions*)arg;
1031 struct disk_part_free_space space; 1031 struct disk_part_free_space space;
1032 daddr_t align; 1032 daddr_t align;
1033 1033
1034 if (parts->dp.num_part >= parts->max_num_parts) 1034 if (parts->dp.num_part >= parts->max_num_parts)
1035 return false; 1035 return false;
1036 1036
1037 align = gpt_get_part_alignment(arg); 1037 align = gpt_get_part_alignment(arg);
1038 if (parts->dp.free_space <= align) 1038 if (parts->dp.free_space <= align)
1039 return false; 1039 return false;
1040 1040
1041 if (gpt_get_free_spaces_internal(parts, &space, 1, align, align, 1041 if (gpt_get_free_spaces_internal(parts, &space, 1, align, align,
1042 0, -1) < 1) 1042 0, -1) < 1)
1043 return false; 1043 return false;
1044 1044
1045 return true; 1045 return true;
1046} 1046}
1047 1047
1048static bool 1048static bool
1049gpt_info_to_part(struct gpt_part_entry *p, const struct disk_part_info *info, 1049gpt_info_to_part(struct gpt_part_entry *p, const struct disk_part_info *info,
1050 const char **err_msg) 1050 const char **err_msg)
1051{ 1051{
1052 p->gp_type = gpt_find_native_type(info->nat_type); 1052 p->gp_type = gpt_find_native_type(info->nat_type);
1053 p->gp_start = info->start; 1053 p->gp_start = info->start;
1054 p->gp_size = info->size; 1054 p->gp_size = info->size;
1055 if (info->last_mounted != NULL && info->last_mounted != 1055 if (info->last_mounted != NULL && info->last_mounted !=
1056 p->last_mounted) { 1056 p->last_mounted) {
1057 free(__UNCONST(p->last_mounted)); 1057 free(__UNCONST(p->last_mounted));
1058 p->last_mounted = strdup(info->last_mounted); 1058 p->last_mounted = strdup(info->last_mounted);
1059 } 1059 }
1060 p->fs_type = info->fs_type; 1060 p->fs_type = info->fs_type;
1061 p->fs_sub_type = info->fs_sub_type; 1061 p->fs_sub_type = info->fs_sub_type;
1062 p->fs_opt1 = info->fs_opt1; 1062 p->fs_opt1 = info->fs_opt1;
1063 p->fs_opt2 = info->fs_opt2; 1063 p->fs_opt2 = info->fs_opt2;
1064 p->fs_opt3 = info->fs_opt3; 1064 p->fs_opt3 = info->fs_opt3;
1065 1065
1066 return true; 1066 return true;
1067} 1067}
1068 1068
1069static part_id 1069static part_id
1070gpt_add_part(struct disk_partitions *arg, 1070gpt_add_part(struct disk_partitions *arg,
1071 const struct disk_part_info *info, const char **err_msg) 1071 const struct disk_part_info *info, const char **err_msg)
1072{ 1072{
1073 struct gpt_disk_partitions *parts = 1073 struct gpt_disk_partitions *parts =
1074 (struct gpt_disk_partitions*)arg; 1074 (struct gpt_disk_partitions*)arg;
1075 struct disk_part_free_space space; 1075 struct disk_part_free_space space;
1076 struct disk_part_info data = *info; 1076 struct disk_part_info data = *info;
1077 struct gpt_part_entry *p; 1077 struct gpt_part_entry *p;
1078 bool ok; 1078 bool ok;
1079 1079
1080 if (err_msg != NULL) 1080 if (err_msg != NULL)
1081 *err_msg = NULL; 1081 *err_msg = NULL;
1082 1082
1083 if (gpt_get_free_spaces_internal(parts, &space, 1, 1, 1, 1083 if (gpt_get_free_spaces_internal(parts, &space, 1, 1, 1,
1084 info->start, -1) < 1) { 1084 info->start, -1) < 1) {
1085 if (err_msg) 1085 if (err_msg)
1086 *err_msg = msg_string(MSG_No_free_space); 1086 *err_msg = msg_string(MSG_No_free_space);
1087 return NO_PART; 1087 return NO_PART;
1088 } 1088 }
1089 if (parts->dp.num_part >= parts->max_num_parts) { 1089 if (parts->dp.num_part >= parts->max_num_parts) {
1090 if (err_msg) 1090 if (err_msg)
1091 *err_msg = msg_string(MSG_err_too_many_partitions); 1091 *err_msg = msg_string(MSG_err_too_many_partitions);
1092 return NO_PART; 1092 return NO_PART;
1093 } 1093 }
1094 1094
1095 if (data.size > space.size) 1095 if (data.size > space.size)
1096 data.size = space.size; 1096 data.size = space.size;
1097 1097
1098 p = calloc(1, sizeof(*p)); 1098 p = calloc(1, sizeof(*p));
1099 if (p == NULL) { 1099 if (p == NULL) {
1100 if (err_msg != NULL) 1100 if (err_msg != NULL)
1101 *err_msg = INTERNAL_ERROR; 1101 *err_msg = INTERNAL_ERROR;
1102 return NO_PART; 1102 return NO_PART;
1103 } 1103 }
1104 if (!gpt_info_to_part(p, &data, err_msg)) { 1104 if (!gpt_info_to_part(p, &data, err_msg)) {
1105 free(p); 1105 free(p);
1106 return NO_PART; 1106 return NO_PART;
1107 } 1107 }
1108 p->gp_flags |= GPEF_MODIFIED; 1108 p->gp_flags |= GPEF_MODIFIED;
1109 ok = gpt_insert_part_into_list(parts, &parts->partitions, p, err_msg); 1109 ok = gpt_insert_part_into_list(parts, &parts->partitions, p, err_msg);
1110 if (ok) { 1110 if (ok) {
1111 parts->dp.num_part++; 1111 parts->dp.num_part++;
1112 parts->dp.free_space -= p->gp_size; 1112 parts->dp.free_space -= p->gp_size;
1113 return parts->dp.num_part-1; 1113 return parts->dp.num_part-1;
1114 } else { 1114 } else {
1115 free(p); 1115 free(p);
1116 return NO_PART; 1116 return NO_PART;
1117 } 1117 }
1118} 1118}
1119 1119
1120static bool 1120static bool
1121gpt_delete_partition(struct disk_partitions *arg, part_id id, 1121gpt_delete_partition(struct disk_partitions *arg, part_id id,
1122 const char **err_msg) 1122 const char **err_msg)
1123{ 1123{
1124 struct gpt_disk_partitions *parts = (struct gpt_disk_partitions*)arg; 1124 struct gpt_disk_partitions *parts = (struct gpt_disk_partitions*)arg;
1125 struct gpt_part_entry *p, *last = NULL; 1125 struct gpt_part_entry *p, *last = NULL;
1126 part_id i; 1126 part_id i;
1127 bool res; 1127 bool res;
1128 1128
1129 if (parts->dp.num_part == 0) 1129 if (parts->dp.num_part == 0)
1130 return false; 1130 return false;
1131 1131
1132 for (i = 0, p = parts->partitions; 1132 for (i = 0, p = parts->partitions;
1133 i != id && i < parts->dp.num_part && p != NULL; 1133 i != id && i < parts->dp.num_part && p != NULL;
1134 i++, p = p->gp_next) 1134 i++, p = p->gp_next)
1135 last = p; 1135 last = p;
1136 1136
1137 if (p == NULL) { 1137 if (p == NULL) {
1138 if (err_msg) 1138 if (err_msg)
1139 *err_msg = INTERNAL_ERROR; 1139 *err_msg = INTERNAL_ERROR;
1140 return false; 1140 return false;
1141 } 1141 }
1142 1142
1143 if (last == NULL) 1143 if (last == NULL)
1144 parts->partitions = p->gp_next; 1144 parts->partitions = p->gp_next;
1145 else 1145 else
1146 last->gp_next = p->gp_next; 1146 last->gp_next = p->gp_next;
1147 1147
1148 res = true; 1148 res = true;
1149 if (p->gp_flags & GPEF_ON_DISK) { 1149 if (p->gp_flags & GPEF_ON_DISK) {
1150 if (!gpt_insert_part_into_list(parts, &parts->obsolete, 1150 if (!gpt_insert_part_into_list(parts, &parts->obsolete,
1151 p, err_msg)) 1151 p, err_msg))
1152 res = false; 1152 res = false;
1153 } else { 1153 } else {
1154 free(p); 1154 free(p);
1155 } 1155 }
1156 1156
1157 if (res) { 1157 if (res) {
1158 parts->dp.num_part--; 1158 parts->dp.num_part--;
1159 parts->dp.free_space += p->gp_size; 1159 parts->dp.free_space += p->gp_size;
1160 } 1160 }
1161 1161
1162 return res; 1162 return res;
1163} 1163}
1164 1164
1165static bool 1165static bool
1166gpt_delete_all_partitions(struct disk_partitions *arg) 1166gpt_delete_all_partitions(struct disk_partitions *arg)
1167{ 1167{
1168 struct gpt_disk_partitions *parts = (struct gpt_disk_partitions*)arg; 1168 struct gpt_disk_partitions *parts = (struct gpt_disk_partitions*)arg;
1169 1169
1170 while (parts->dp.num_part > 0) { 1170 while (parts->dp.num_part > 0) {
1171 if (!gpt_delete_partition(&parts->dp, 0, NULL)) 1171 if (!gpt_delete_partition(&parts->dp, 0, NULL))
1172 return false; 1172 return false;
1173 } 1173 }
1174 1174
1175 return true; 1175 return true;
1176} 1176}
1177 1177
1178static bool 1178static bool
1179gpt_read_part(const char *disk, daddr_t start, struct gpt_part_entry *p) 1179gpt_read_part(const char *disk, daddr_t start, struct gpt_part_entry *p)
1180{ 1180{
1181 char *textbuf, *t, *tt; 1181 char *textbuf, *t, *tt;
1182 static const char expected_hdr[] = "Details for index "; 1182 static const char expected_hdr[] = "Details for index ";
1183 1183
1184 /* run gpt show for this partition */ 1184 /* run gpt show for this partition */
1185 if (collect(T_OUTPUT, &textbuf, 1185 if (collect(T_OUTPUT, &textbuf,
1186 "gpt -r show -b %" PRIu64 " %s 2>/dev/null", start, disk) < 1) 1186 "gpt -r show -b %" PRIu64 " %s 2>/dev/null", start, disk) < 1)
1187 return false; 1187 return false;
1188 1188
1189 /* 1189 /*
1190 * gpt show should respond with single partition details, but will 1190 * gpt show should respond with single partition details, but will
1191 * fall back to "show -a" output if something is wrong 1191 * fall back to "show -a" output if something is wrong
1192 */ 1192 */
1193 t = strtok(textbuf, "\n"); /* first line is special */ 1193 t = strtok(textbuf, "\n"); /* first line is special */
1194 if (strncmp(t, expected_hdr, sizeof(expected_hdr)-1) != 0) { 1194 if (strncmp(t, expected_hdr, sizeof(expected_hdr)-1) != 0) {
1195 free(textbuf); 1195 free(textbuf);
1196 return false; 1196 return false;
1197 } 1197 }
1198 1198
1199 /* parse output into "old" */ 1199 /* parse output into "old" */
1200 while ((t = strtok(NULL, "\n")) != NULL) { 1200 while ((t = strtok(NULL, "\n")) != NULL) {
1201 tt = strsep(&t, " \t"); 1201 tt = strsep(&t, " \t");
1202 if (strlen(tt) == 0) 1202 if (strlen(tt) == 0)
1203 continue; 1203 continue;
1204 gpt_add_info(p, tt, t, true); 1204 gpt_add_info(p, tt, t, true);
1205 } 1205 }
1206 free(textbuf); 1206 free(textbuf);
1207 1207
1208 return true; 1208 return true;
1209} 1209}
1210 1210
1211static bool 1211static bool
1212gpt_apply_attr(const char *disk, const char *cmd, off_t start, uint todo) 1212gpt_apply_attr(const char *disk, const char *cmd, off_t start, uint todo)
1213{ 1213{
1214 size_t i; 1214 size_t i;
1215 char attr_str[STRSIZE]; 1215 char attr_str[STRSIZE];
1216 1216
1217 if (todo == 0) 1217 if (todo == 0)
1218 return true; 1218 return true;
1219 1219
1220 strcpy(attr_str, "-a "); 1220 strcpy(attr_str, "-a ");
1221 for (i = 0; todo != 0; i++) { 1221 for (i = 0; todo != 0; i++) {
1222 if (!(gpt_avail_attrs[i].flag & todo)) 1222 if (!(gpt_avail_attrs[i].flag & todo))
1223 continue; 1223 continue;
1224 todo &= ~gpt_avail_attrs[i].flag; 1224 todo &= ~gpt_avail_attrs[i].flag;
1225 if (attr_str[0]) 1225 if (attr_str[0])
1226 strlcat(attr_str, ",", 1226 strlcat(attr_str, ",",
1227 sizeof(attr_str)); 1227 sizeof(attr_str));
1228 strlcat(attr_str, 1228 strlcat(attr_str,
1229 gpt_avail_attrs[i].name, 1229 gpt_avail_attrs[i].name,
1230 sizeof(attr_str)); 1230 sizeof(attr_str));
1231 } 1231 }
1232 if (run_program(RUN_SILENT, 1232 if (run_program(RUN_SILENT,
1233 "gpt %s %s -b %" PRIu64 " %s", cmd, attr_str, start, disk) != 0) 1233 "gpt %s %s -b %" PRIu64 " %s", cmd, attr_str, start, disk) != 0)
1234 return false; 1234 return false;
1235 return true; 1235 return true;
1236} 1236}
1237 1237
1238/* 1238/*
1239 * Modify an existing on-disk partition. 1239 * Modify an existing on-disk partition.
1240 * Start and size can not be changed here, caller needs to deal 1240 * Start and size can not be changed here, caller needs to deal
1241 * with that kind of changes upfront. 1241 * with that kind of changes upfront.
1242 */ 1242 */
1243static bool 1243static bool
1244gpt_modify_part(const char *disk, struct gpt_part_entry *p) 1244gpt_modify_part(const char *disk, struct gpt_part_entry *p)
1245{ 1245{
1246 struct gpt_part_entry old; 1246 struct gpt_part_entry old;
1247 uint todo_set, todo_unset; 1247 uint todo_set, todo_unset;
1248 1248
1249 /* 1249 /*
1250 * Query current on-disk state 1250 * Query current on-disk state
1251 */ 1251 */
1252 memset(&old, 0, sizeof old); 1252 memset(&old, 0, sizeof old);
1253 if (!gpt_read_part(disk, p->gp_start, &old)) 1253 if (!gpt_read_part(disk, p->gp_start, &old))
1254 return false; 1254 return false;
1255 1255
1256 /* Reject unsupported changes */ 1256 /* Reject unsupported changes */
1257 if (old.gp_start != p->gp_start || old.gp_size != p->gp_size) 1257 if (old.gp_start != p->gp_start || old.gp_size != p->gp_size)
1258 return false; 1258 return false;
1259 1259
1260 /* 1260 /*
1261 * GUID should never change, but the internal copy 1261 * GUID should never change, but the internal copy
1262 * may not yet know it. 1262 * may not yet know it.
1263 */ 1263 */
1264 strcpy(p->gp_id, old.gp_id); 1264 strcpy(p->gp_id, old.gp_id);
1265 1265
1266 /* Check type */ 1266 /* Check type */
1267 if (p->gp_type != old.gp_type) { 1267 if (p->gp_type != old.gp_type) {
1268 if (run_program(RUN_SILENT, 1268 if (run_program(RUN_SILENT,
1269 "gpt type -b %" PRIu64 " -T %s %s", 1269 "gpt type -b %" PRIu64 " -T %s %s",
1270 p->gp_start, p->gp_type->tid, disk) != 0) 1270 p->gp_start, p->gp_type->tid, disk) != 0)
1271 return false; 1271 return false;
1272 } 1272 }
1273 1273
1274 /* Check label */ 1274 /* Check label */
1275 if (strcmp(p->gp_label, old.gp_label) != 0) { 1275 if (strcmp(p->gp_label, old.gp_label) != 0) {
1276 if (run_program(RUN_SILENT, 1276 if (run_program(RUN_SILENT,
1277 "gpt label -b %" PRIu64 " -l \'%s\' %s", 1277 "gpt label -b %" PRIu64 " -l \'%s\' %s",
1278 p->gp_start, p->gp_label, disk) != 0) 1278 p->gp_start, p->gp_label, disk) != 0)
1279 return false; 1279 return false;
1280 } 1280 }
1281 1281
1282 /* Check attributes */ 1282 /* Check attributes */
1283 if (p->gp_attr != old.gp_attr) { 1283 if (p->gp_attr != old.gp_attr) {
1284 if (p->gp_attr == 0) { 1284 if (p->gp_attr == 0) {
1285 if (run_program(RUN_SILENT, 1285 if (run_program(RUN_SILENT,
1286 "gpt set -N -b %" PRIu64 " %s", 1286 "gpt set -N -b %" PRIu64 " %s",
1287 p->gp_start, disk) != 0) 1287 p->gp_start, disk) != 0)
1288 return false; 1288 return false;
1289 } else { 1289 } else {
1290 todo_set = (p->gp_attr ^ old.gp_attr) & p->gp_attr; 1290 todo_set = (p->gp_attr ^ old.gp_attr) & p->gp_attr;
1291 todo_unset = (p->gp_attr ^ old.gp_attr) & old.gp_attr; 1291 todo_unset = (p->gp_attr ^ old.gp_attr) & old.gp_attr;
1292 if (!gpt_apply_attr(disk, "unset", p->gp_start, 1292 if (!gpt_apply_attr(disk, "unset", p->gp_start,
1293 todo_unset)) 1293 todo_unset))
1294 return false; 1294 return false;
1295 if (!gpt_apply_attr(disk, "set", p->gp_start, 1295 if (!gpt_apply_attr(disk, "set", p->gp_start,
1296 todo_set)) 1296 todo_set))
1297 return false; 1297 return false;
1298 } 1298 }
1299 } 1299 }
1300 1300
1301 return true; 1301 return true;
1302} 1302}
1303 1303
1304/* 1304/*
1305 * verbatim copy from sys/dev/dkwedge/dkwedge_bsdlabel.c: 1305 * verbatim copy from sys/dev/dkwedge/dkwedge_bsdlabel.c:
1306 * map FS_* to wedge strings 1306 * map FS_* to wedge strings
1307 */ 1307 */
1308static const char * 1308static const char *
1309bsdlabel_fstype_to_str(uint8_t fstype) 1309bsdlabel_fstype_to_str(uint8_t fstype)
1310{ 1310{
1311 const char *str; 1311 const char *str;
1312 1312
1313 /* 1313 /*
1314 * For each type known to FSTYPE_DEFN (from <sys/disklabel.h>), 1314 * For each type known to FSTYPE_DEFN (from <sys/disklabel.h>),
1315 * a suitable case branch will convert the type number to a string. 1315 * a suitable case branch will convert the type number to a string.
1316 */ 1316 */
1317 switch (fstype) { 1317 switch (fstype) {
1318#define FSTYPE_TO_STR_CASE(tag, number, name, fsck, mount) \ 1318#define FSTYPE_TO_STR_CASE(tag, number, name, fsck, mount) \
1319 case __CONCAT(FS_,tag): str = __CONCAT(DKW_PTYPE_,tag); break; 1319 case __CONCAT(FS_,tag): str = __CONCAT(DKW_PTYPE_,tag); break;
1320 FSTYPE_DEFN(FSTYPE_TO_STR_CASE) 1320 FSTYPE_DEFN(FSTYPE_TO_STR_CASE)
1321#undef FSTYPE_TO_STR_CASE 1321#undef FSTYPE_TO_STR_CASE
1322 default: str = NULL; break; 1322 default: str = NULL; break;
1323 } 1323 }
1324 1324
1325 return (str); 1325 return (str);
1326} 1326}
1327 1327
1328static bool 1328static bool
1329gpt_add_wedge(const char *disk, struct gpt_part_entry *p) 1329gpt_add_wedge(const char *disk, struct gpt_part_entry *p)
1330{ 1330{
1331 struct dkwedge_info dkw; 1331 struct dkwedge_info dkw;
1332 const char *tname; 1332 const char *tname;
1333 char diskpath[MAXPATHLEN]; 1333 char diskpath[MAXPATHLEN];
1334 int fd; 1334 int fd;
1335 1335
1336 memset(&dkw, 0, sizeof(dkw)); 1336 memset(&dkw, 0, sizeof(dkw));
1337 tname = bsdlabel_fstype_to_str(p->fs_type); 1337 tname = bsdlabel_fstype_to_str(p->fs_type);
1338 if (tname) 1338 if (tname)
1339 strlcpy(dkw.dkw_ptype, tname, sizeof(dkw.dkw_ptype)); 1339 strlcpy(dkw.dkw_ptype, tname, sizeof(dkw.dkw_ptype));
1340 1340
1341 strlcpy((char*)&dkw.dkw_wname, p->gp_id, sizeof(dkw.dkw_wname)); 1341 strlcpy((char*)&dkw.dkw_wname, p->gp_id, sizeof(dkw.dkw_wname));
1342 dkw.dkw_offset = p->gp_start; 1342 dkw.dkw_offset = p->gp_start;
1343 dkw.dkw_size = p->gp_size; 1343 dkw.dkw_size = p->gp_size;
1344 if (dkw.dkw_wname[0] == 0) { 1344 if (dkw.dkw_wname[0] == 0) {
1345 if (p->gp_label[0] != 0) 1345 if (p->gp_label[0] != 0)
1346 strlcpy((char*)&dkw.dkw_wname, 1346 strlcpy((char*)&dkw.dkw_wname,
1347 p->gp_label, sizeof(dkw.dkw_wname)); 1347 p->gp_label, sizeof(dkw.dkw_wname));
1348 } 1348 }
1349 if (dkw.dkw_wname[0] == 0) { 1349 if (dkw.dkw_wname[0] == 0) {
1350 snprintf((char*)dkw.dkw_wname, sizeof dkw.dkw_wname, 1350 snprintf((char*)dkw.dkw_wname, sizeof dkw.dkw_wname,
1351 "%s_%" PRIi64 "@%" PRIi64, disk, p->gp_size, p->gp_start); 1351 "%s_%" PRIi64 "@%" PRIi64, disk, p->gp_size, p->gp_start);
1352 } 1352 }
1353 1353
1354 fd = opendisk(disk, O_RDWR, diskpath, sizeof(diskpath), 0); 1354 fd = opendisk(disk, O_RDWR, diskpath, sizeof(diskpath), 0);
1355 if (fd < 0) 1355 if (fd < 0)
1356 return false; 1356 return false;
1357 if (ioctl(fd, DIOCAWEDGE, &dkw) == -1) { 1357 if (ioctl(fd, DIOCAWEDGE, &dkw) == -1) {
1358 close(fd); 1358 close(fd);
1359 return false; 1359 return false;
1360 } 1360 }
1361 close(fd); 1361 close(fd);
1362 1362
1363 strlcpy(p->gp_dev_name, dkw.dkw_devname, sizeof(p->gp_dev_name)); 1363 strlcpy(p->gp_dev_name, dkw.dkw_devname, sizeof(p->gp_dev_name));
1364 p->gp_flags |= GPEF_WEDGE; 1364 p->gp_flags |= GPEF_WEDGE;
1365 return true; 1365 return true;
1366} 1366}
1367 1367
1368static void 1368static void
1369escape_spaces(char *dest, const char *src) 1369escape_spaces(char *dest, const char *src)
1370{ 1370{
1371 unsigned char c; 1371 unsigned char c;
1372 1372
1373 while (*src) { 1373 while (*src) {
1374 c = *src++; 1374 c = *src++;
1375 if (isspace(c) || c == '\\') 1375 if (isspace(c) || c == '\\')
1376 *dest++ = '\\'; 1376 *dest++ = '\\';
1377 *dest++ = c; 1377 *dest++ = c;
1378 } 1378 }
1379 *dest = 0; 1379 *dest = 0;
1380} 1380}
1381 1381
1382static bool 1382static bool
1383gpt_get_part_device(const struct disk_partitions *arg, 1383gpt_get_part_device(const struct disk_partitions *arg,
1384 part_id id, char *devname, size_t max_devname_len, int *part, 1384 part_id id, char *devname, size_t max_devname_len, int *part,
1385 enum dev_name_usage usage, bool with_path, bool life) 1385 enum dev_name_usage usage, bool with_path, bool life)
1386{ 1386{
1387 const struct gpt_disk_partitions *parts = 1387 const struct gpt_disk_partitions *parts =
1388 (const struct gpt_disk_partitions*)arg; 1388 (const struct gpt_disk_partitions*)arg;
1389 struct gpt_part_entry *p = parts->partitions; 1389 struct gpt_part_entry *p = parts->partitions;
1390 char tmpname[GPT_LABEL_LEN*2]; 1390 char tmpname[GPT_LABEL_LEN*2];
1391 part_id no; 1391 part_id no;
1392 1392
1393 1393
1394 for (no = 0; p != NULL && no < id; no++) 1394 for (no = 0; p != NULL && no < id; no++)
1395 p = p->gp_next; 1395 p = p->gp_next;
1396 1396
1397 if (no != id || p == NULL) 1397 if (no != id || p == NULL)
1398 return false; 1398 return false;
1399 1399
1400 if (part) 1400 if (part)
1401 *part = -1; 1401 *part = -1;
1402 1402
1403 if (usage == logical_name && p->gp_label[0] == 0 && p->gp_id[0] == 0) 1403 if (usage == logical_name && p->gp_label[0] == 0 && p->gp_id[0] == 0)
1404 usage = plain_name; 1404 usage = plain_name;
1405 if (usage == plain_name || usage == raw_dev_name) 1405 if (usage == plain_name || usage == raw_dev_name)
1406 life = true; 1406 life = true;
1407 if (!(p->gp_flags & GPEF_WEDGE) && life) 1407 if (!(p->gp_flags & GPEF_WEDGE) && life &&
1408 gpt_add_wedge(arg->disk, p); 1408 !gpt_add_wedge(arg->disk, p)) {
 1409 devname[0] = 0;
 1410 return false;
 1411 }
1409 1412
1410 switch (usage) { 1413 switch (usage) {
1411 case logical_name: 1414 case logical_name:
1412 if (p->gp_label[0] != 0) { 1415 if (p->gp_label[0] != 0) {
1413 escape_spaces(tmpname, p->gp_label); 1416 escape_spaces(tmpname, p->gp_label);
1414 snprintf(devname, max_devname_len, 1417 snprintf(devname, max_devname_len,
1415 "NAME=%s", tmpname); 1418 "NAME=%s", tmpname);
1416 } else { 1419 } else {
1417 snprintf(devname, max_devname_len, 1420 snprintf(devname, max_devname_len,
1418 "NAME=%s", p->gp_id); 1421 "NAME=%s", p->gp_id);
1419 } 1422 }
1420 break; 1423 break;
1421 case plain_name: 1424 case plain_name:
1422 assert(p->gp_flags & GPEF_WEDGE); 1425 assert(p->gp_flags & GPEF_WEDGE);
1423 if (with_path) 1426 if (with_path)
1424 snprintf(devname, max_devname_len, _PATH_DEV "%s", 1427 snprintf(devname, max_devname_len, _PATH_DEV "%s",
1425 p->gp_dev_name); 1428 p->gp_dev_name);
1426 else 1429 else
1427 strlcpy(devname, p->gp_dev_name, max_devname_len); 1430 strlcpy(devname, p->gp_dev_name, max_devname_len);
1428 break; 1431 break;
1429 case raw_dev_name: 1432 case raw_dev_name:
1430 assert(p->gp_flags & GPEF_WEDGE); 1433 assert(p->gp_flags & GPEF_WEDGE);
1431 if (with_path) 1434 if (with_path)
1432 snprintf(devname, max_devname_len, _PATH_DEV "r%s", 1435 snprintf(devname, max_devname_len, _PATH_DEV "r%s",
1433 p->gp_dev_name); 1436 p->gp_dev_name);
1434 else 1437 else
1435 snprintf(devname, max_devname_len, "r%s", 1438 snprintf(devname, max_devname_len, "r%s",
1436 p->gp_dev_name); 1439 p->gp_dev_name);
1437 break; 1440 break;
1438 default: 1441 default:
1439 return false; 1442 return false;
1440 } 1443 }
1441 1444
1442 return true; 1445 return true;
1443} 1446}
1444 1447
1445static bool 1448static bool
1446gpt_write_to_disk(struct disk_partitions *arg) 1449gpt_write_to_disk(struct disk_partitions *arg)
1447{ 1450{
1448 struct gpt_disk_partitions *parts = (struct gpt_disk_partitions*)arg; 1451 struct gpt_disk_partitions *parts = (struct gpt_disk_partitions*)arg;
1449 struct gpt_part_entry *p, *n; 1452 struct gpt_part_entry *p, *n;
1450 char label_arg[sizeof(p->gp_label) + 10]; 1453 char label_arg[sizeof(p->gp_label) + 10];
1451 char diskpath[MAXPATHLEN]; 1454 char diskpath[MAXPATHLEN];
1452 int fd, bits = 0; 1455 int fd, bits = 0;
1453 bool root_is_new = false, efi_is_new = false; 1456 bool root_is_new = false, efi_is_new = false;
1454 part_id root_id = NO_PART, efi_id = NO_PART, pno; 1457 part_id root_id = NO_PART, efi_id = NO_PART, pno;
1455 1458
1456 /* 1459 /*
1457 * Remove all wedges on this disk - they may become invalid and we 1460 * Remove all wedges on this disk - they may become invalid and we
1458 * have no easy way to associate them with the partitioning data. 1461 * have no easy way to associate them with the partitioning data.
1459 * Instead we will explicitly request creation of wedges on demand 1462 * Instead we will explicitly request creation of wedges on demand
1460 * later. 1463 * later.
1461 */ 1464 */
1462 fd = opendisk(arg->disk, O_RDWR, diskpath, sizeof(diskpath), 0); 1465 fd = opendisk(arg->disk, O_RDWR, diskpath, sizeof(diskpath), 0);
1463 if (fd < 0) 1466 if (fd < 0)
1464 return false; 1467 return false;
1465 if (ioctl(fd, DIOCRMWEDGES, &bits) == -1) 1468 if (ioctl(fd, DIOCRMWEDGES, &bits) == -1)
1466 return false; 1469 return false;
1467 close(fd); 1470 close(fd);
1468 1471
1469 /* 1472 /*
1470 * Collect first root and efi partition (if available), clear 1473 * Collect first root and efi partition (if available), clear
1471 * "have wedge" flags. 1474 * "have wedge" flags.
1472 */ 1475 */
1473 for (pno = 0, p = parts->partitions; p != NULL; p = p->gp_next, pno++) { 1476 for (pno = 0, p = parts->partitions; p != NULL; p = p->gp_next, pno++) {
1474 p->gp_flags &= ~GPEF_WEDGE; 1477 p->gp_flags &= ~GPEF_WEDGE;
1475 if (root_id == NO_PART && p->gp_type != NULL) { 1478 if (root_id == NO_PART && p->gp_type != NULL) {
1476 if (p->gp_type->gent.generic_ptype == PT_root && 1479 if (p->gp_type->gent.generic_ptype == PT_root &&
1477 (p->gp_flags & GPEF_TARGET)) { 1480 (p->gp_flags & GPEF_TARGET)) {
1478 root_id = pno; 1481 root_id = pno;
1479 root_is_new = !(p->gp_flags & GPEF_ON_DISK); 1482 root_is_new = !(p->gp_flags & GPEF_ON_DISK);
1480 } else if (efi_id == NO_PART && 1483 } else if (efi_id == NO_PART &&
1481 p->gp_type->gent.generic_ptype == PT_EFI_SYSTEM) { 1484 p->gp_type->gent.generic_ptype == PT_EFI_SYSTEM) {
1482 efi_id = pno; 1485 efi_id = pno;
1483 efi_is_new = !(p->gp_flags & GPEF_ON_DISK); 1486 efi_is_new = !(p->gp_flags & GPEF_ON_DISK);
1484 } 1487 }
1485 } 1488 }
1486 } 1489 }
1487 1490
1488 /* 1491 /*
1489 * If no GPT on disk yet, create it. 1492 * If no GPT on disk yet, create it.
1490 */ 1493 */
1491 if (!parts->has_gpt) { 1494 if (!parts->has_gpt) {
1492 char limit[30]; 1495 char limit[30];
1493 1496
1494 if (parts->max_num_parts > 0) 1497 if (parts->max_num_parts > 0)
1495 sprintf(limit, "-p %zu", parts->max_num_parts); 1498 sprintf(limit, "-p %zu", parts->max_num_parts);
1496 else 1499 else
1497 limit[0] = 0; 1500 limit[0] = 0;
1498 if (run_program(RUN_SILENT, "gpt create %s %s", 1501 if (run_program(RUN_SILENT, "gpt create %s %s",
1499 limit, parts->dp.disk)) 1502 limit, parts->dp.disk))
1500 return false; 1503 return false;
1501 parts->has_gpt = true; 1504 parts->has_gpt = true;
1502 } 1505 }
1503 1506
1504 /* 1507 /*
1505 * Delete all old partitions 1508 * Delete all old partitions
1506 */ 1509 */
1507 for (p = parts->obsolete; p != NULL; p = n) { 1510 for (p = parts->obsolete; p != NULL; p = n) {
1508 run_program(RUN_SILENT, "gpt -n remove -b %" PRIu64 " %s", 1511 run_program(RUN_SILENT, "gpt -n remove -b %" PRIu64 " %s",
1509 p->gp_start, arg->disk); 1512 p->gp_start, arg->disk);
1510 n = p->gp_next; 1513 n = p->gp_next;
1511 free(p); 1514 free(p);
1512 } 1515 }
1513 parts->obsolete = NULL; 1516 parts->obsolete = NULL;
1514 1517
1515 /* 1518 /*
1516 * Modify existing but changed partitions 1519 * Modify existing but changed partitions
1517 */ 1520 */
1518 for (p = parts->partitions; p != NULL; p = p->gp_next) { 1521 for (p = parts->partitions; p != NULL; p = p->gp_next) {
1519 if (!(p->gp_flags & GPEF_ON_DISK)) 1522 if (!(p->gp_flags & GPEF_ON_DISK))
1520 continue; 1523 continue;
1521 1524
1522 if (p->gp_flags & GPEF_RESIZED) { 1525 if (p->gp_flags & GPEF_RESIZED) {
1523 run_program(RUN_SILENT, 1526 run_program(RUN_SILENT,
1524 "gpt -n resize -b %" PRIu64 " -s %" PRIu64 "s %s", 1527 "gpt -n resize -b %" PRIu64 " -s %" PRIu64 "s %s",
1525 p->gp_start, p->gp_size, arg->disk); 1528 p->gp_start, p->gp_size, arg->disk);
1526 p->gp_flags &= ~GPEF_RESIZED; 1529 p->gp_flags &= ~GPEF_RESIZED;
1527 } 1530 }
1528 1531
1529 if (!(p->gp_flags & GPEF_MODIFIED)) 1532 if (!(p->gp_flags & GPEF_MODIFIED))
1530 continue; 1533 continue;
1531 1534
1532 if (!gpt_modify_part(parts->dp.disk, p)) 1535 if (!gpt_modify_part(parts->dp.disk, p))
1533 return false; 1536 return false;
1534 } 1537 }
1535 1538
1536 /* 1539 /*
1537 * Add new partitions 1540 * Add new partitions
1538 */ 1541 */
1539 for (p = parts->partitions; p != NULL; p = p->gp_next) { 1542 for (p = parts->partitions; p != NULL; p = p->gp_next) {
1540 if (p->gp_flags & GPEF_ON_DISK) 1543 if (p->gp_flags & GPEF_ON_DISK)
1541 continue; 1544 continue;
1542 if (!(p->gp_flags & GPEF_MODIFIED)) 1545 if (!(p->gp_flags & GPEF_MODIFIED))
1543 continue; 1546 continue;
1544 1547
1545 if (p->gp_label[0] == 0) 1548 if (p->gp_label[0] == 0)
1546 label_arg[0] = 0; 1549 label_arg[0] = 0;
1547 else 1550 else
1548 sprintf(label_arg, "-l \'%s\'", p->gp_label); 1551 sprintf(label_arg, "-l \'%s\'", p->gp_label);
1549 1552
1550 if (p->gp_type != NULL) 1553 if (p->gp_type != NULL)
1551 run_program(RUN_SILENT, 1554 run_program(RUN_SILENT,
1552 "gpt -n add -b %" PRIu64 " -s %" PRIu64 1555 "gpt -n add -b %" PRIu64 " -s %" PRIu64
1553 "s -t %s %s %s", 1556 "s -t %s %s %s",
1554 p->gp_start, p->gp_size, p->gp_type->tid, 1557 p->gp_start, p->gp_size, p->gp_type->tid,
1555 label_arg, arg->disk); 1558 label_arg, arg->disk);
1556 else 1559 else
1557 run_program(RUN_SILENT, 1560 run_program(RUN_SILENT,
1558 "gpt -n add -b %" PRIu64 " -s %" PRIu64 1561 "gpt -n add -b %" PRIu64 " -s %" PRIu64
1559 "s %s %s", 1562 "s %s %s",
1560 p->gp_start, p->gp_size, label_arg, arg->disk); 1563 p->gp_start, p->gp_size, label_arg, arg->disk);
1561 gpt_apply_attr(arg->disk, "set", p->gp_start, p->gp_attr); 1564 gpt_apply_attr(arg->disk, "set", p->gp_start, p->gp_attr);
1562 gpt_read_part(arg->disk, p->gp_start, p); 1565 gpt_read_part(arg->disk, p->gp_start, p);
1563 p->gp_flags |= GPEF_ON_DISK; 1566 p->gp_flags |= GPEF_ON_DISK;
1564 } 1567 }
1565 1568
1566 /* 1569 /*
1567 * Additional MD bootloader magic... 1570 * Additional MD bootloader magic...
1568 */ 1571 */
1569 if (!md_gpt_post_write(&parts->dp, root_id, root_is_new, efi_id, 1572 if (!md_gpt_post_write(&parts->dp, root_id, root_is_new, efi_id,
1570 efi_is_new)) 1573 efi_is_new))
1571 return false; 1574 return false;
1572 1575
1573 return true; 1576 return true;
1574} 1577}
1575 1578
1576static part_id 1579static part_id
1577gpt_find_by_name(struct disk_partitions *arg, const char *name) 1580gpt_find_by_name(struct disk_partitions *arg, const char *name)
1578{ 1581{
1579 struct gpt_disk_partitions *parts = (struct gpt_disk_partitions*)arg; 1582 struct gpt_disk_partitions *parts = (struct gpt_disk_partitions*)arg;
1580 struct gpt_part_entry *p; 1583 struct gpt_part_entry *p;
1581 part_id pno; 1584 part_id pno;
1582 1585
1583 for (pno = 0, p = parts->partitions; p != NULL; 1586 for (pno = 0, p = parts->partitions; p != NULL;
1584 p = p->gp_next, pno++) { 1587 p = p->gp_next, pno++) {
1585 if (strcmp(p->gp_label, name) == 0) 1588 if (strcmp(p->gp_label, name) == 0)
1586 return pno; 1589 return pno;
1587 if (strcmp(p->gp_id, name) == 0) 1590 if (strcmp(p->gp_id, name) == 0)
1588 return pno; 1591 return pno;
1589 } 1592 }
1590 1593
1591 return NO_PART; 1594 return NO_PART;
1592} 1595}
1593 1596
1594bool 1597bool
1595gpt_parts_check(void) 1598gpt_parts_check(void)
1596{ 1599{
1597 1600
1598 check_available_binaries(); 1601 check_available_binaries();
1599 1602
1600 return have_gpt && have_dk; 1603 return have_gpt && have_dk;
1601} 1604}
1602 1605
1603static void 1606static void
1604gpt_free(struct disk_partitions *arg) 1607gpt_free(struct disk_partitions *arg)
1605{ 1608{
1606 struct gpt_disk_partitions *parts = (struct gpt_disk_partitions*)arg; 1609 struct gpt_disk_partitions *parts = (struct gpt_disk_partitions*)arg;
1607 struct gpt_part_entry *p, *n; 1610 struct gpt_part_entry *p, *n;
1608 1611
1609 assert(parts != NULL); 1612 assert(parts != NULL);
1610 for (p = parts->partitions; p != NULL; p = n) { 1613 for (p = parts->partitions; p != NULL; p = n) {
1611 free(__UNCONST(p->last_mounted)); 1614 free(__UNCONST(p->last_mounted));
1612 n = p->gp_next; 1615 n = p->gp_next;
1613 free(p); 1616 free(p);
1614 } 1617 }
1615 free(__UNCONST(parts->dp.disk)); 1618 free(__UNCONST(parts->dp.disk));
1616 free(parts); 1619 free(parts);
1617} 1620}
1618 1621
1619static void 1622static void
1620gpt_destroy_part_scheme(struct disk_partitions *arg) 1623gpt_destroy_part_scheme(struct disk_partitions *arg)
1621{ 1624{
1622 1625
1623 run_program(RUN_SILENT, "gpt destroy %s", arg->disk); 1626 run_program(RUN_SILENT, "gpt destroy %s", arg->disk);
1624 gpt_free(arg); 1627 gpt_free(arg);
1625} 1628}
1626 1629
1627static bool 1630static bool
1628gpt_custom_attribute_writable(const struct disk_partitions *arg, 1631gpt_custom_attribute_writable(const struct disk_partitions *arg,
1629 part_id ptn, size_t attr_no) 1632 part_id ptn, size_t attr_no)
1630{ 1633{
1631 const struct gpt_disk_partitions *parts = 1634 const struct gpt_disk_partitions *parts =
1632 (const struct gpt_disk_partitions*)arg; 1635 (const struct gpt_disk_partitions*)arg;
1633 size_t i; 1636 size_t i;
1634 struct gpt_part_entry *p; 1637 struct gpt_part_entry *p;
1635 1638
1636 if (attr_no >= arg->pscheme->custom_attribute_count) 1639 if (attr_no >= arg->pscheme->custom_attribute_count)
1637 return false; 1640 return false;
1638 1641
1639 const msg label = arg->pscheme->custom_attributes[attr_no].label; 1642 const msg label = arg->pscheme->custom_attributes[attr_no].label;
1640 1643
1641 /* we can not edit the uuid attribute */ 1644 /* we can not edit the uuid attribute */
1642 if (label == MSG_ptn_uuid) 1645 if (label == MSG_ptn_uuid)
1643 return false; 1646 return false;
1644 1647
1645 /* the label is always editable */ 1648 /* the label is always editable */
1646 if (label == MSG_ptn_label) 1649 if (label == MSG_ptn_label)
1647 return true; 1650 return true;
1648 1651
1649 /* the GPT type is read only */ 1652 /* the GPT type is read only */
1650 if (label == MSG_ptn_gpt_type) 1653 if (label == MSG_ptn_gpt_type)
1651 return false; 1654 return false;
1652 1655
1653 /* BOOTME makes no sense on swap partitions */ 1656 /* BOOTME makes no sense on swap partitions */
1654 for (i = 0, p = parts->partitions; p != NULL; i++, p = p->gp_next) 1657 for (i = 0, p = parts->partitions; p != NULL; i++, p = p->gp_next)
1655 if (i == ptn) 1658 if (i == ptn)
1656 break; 1659 break;
1657 1660
1658 if (p == NULL) 1661 if (p == NULL)
1659 return false; 1662 return false;
1660 1663
1661 if (p->fs_type == FS_SWAP || 1664 if (p->fs_type == FS_SWAP ||
1662 (p->gp_type != NULL && p->gp_type->gent.generic_ptype == PT_swap)) 1665 (p->gp_type != NULL && p->gp_type->gent.generic_ptype == PT_swap))
1663 return false; 1666 return false;
1664 1667
1665 return true; 1668 return true;
1666} 1669}
1667 1670
1668static const char * 1671static const char *
1669gpt_get_label_str(const struct disk_partitions *arg, part_id ptn) 1672gpt_get_label_str(const struct disk_partitions *arg, part_id ptn)
1670{ 1673{
1671 const struct gpt_disk_partitions *parts = 1674 const struct gpt_disk_partitions *parts =
1672 (const struct gpt_disk_partitions*)arg; 1675 (const struct gpt_disk_partitions*)arg;
1673 size_t i; 1676 size_t i;
1674 struct gpt_part_entry *p; 1677 struct gpt_part_entry *p;
1675 1678
1676 for (i = 0, p = parts->partitions; p != NULL; i++, p = p->gp_next) 1679 for (i = 0, p = parts->partitions; p != NULL; i++, p = p->gp_next)
1677 if (i == ptn) 1680 if (i == ptn)
1678 break; 1681 break;
1679 1682
1680 if (p == NULL) 1683 if (p == NULL)
1681 return NULL; 1684 return NULL;
1682 1685
1683 if (p->gp_label[0] != 0) 1686 if (p->gp_label[0] != 0)
1684 return p->gp_label; 1687 return p->gp_label;
1685 return p->gp_id; 1688 return p->gp_id;
1686} 1689}
1687 1690
1688static bool 1691static bool
1689gpt_format_custom_attribute(const struct disk_partitions *arg, 1692gpt_format_custom_attribute(const struct disk_partitions *arg,
1690 part_id ptn, size_t attr_no, const struct disk_part_info *info, 1693 part_id ptn, size_t attr_no, const struct disk_part_info *info,
1691 char *out, size_t out_space) 1694 char *out, size_t out_space)
1692{ 1695{
1693 const struct gpt_disk_partitions *parts = 1696 const struct gpt_disk_partitions *parts =
1694 (const struct gpt_disk_partitions*)arg; 1697 (const struct gpt_disk_partitions*)arg;
1695 size_t i; 1698 size_t i;
1696 struct gpt_part_entry *p, data; 1699 struct gpt_part_entry *p, data;
1697 1700
1698 for (i = 0, p = parts->partitions; p != NULL; i++, p = p->gp_next) 1701 for (i = 0, p = parts->partitions; p != NULL; i++, p = p->gp_next)
1699 if (i == ptn) 1702 if (i == ptn)
1700 break; 1703 break;
1701 1704
1702 if (p == NULL) 1705 if (p == NULL)
1703 return false; 1706 return false;
1704 1707
1705 if (attr_no >= parts->dp.pscheme->custom_attribute_count) 1708 if (attr_no >= parts->dp.pscheme->custom_attribute_count)
1706 return false; 1709 return false;
1707 1710
1708 const msg label = parts->dp.pscheme->custom_attributes[attr_no].label; 1711 const msg label = parts->dp.pscheme->custom_attributes[attr_no].label;
1709 1712
1710 if (info != NULL) { 1713 if (info != NULL) {
1711 data = *p; 1714 data = *p;
1712 gpt_info_to_part(&data, info, NULL); 1715 gpt_info_to_part(&data, info, NULL);
1713 p = &data; 1716 p = &data;
1714 } 1717 }
1715 1718
1716 if (label == MSG_ptn_label) 1719 if (label == MSG_ptn_label)
1717 strlcpy(out, p->gp_label, out_space); 1720 strlcpy(out, p->gp_label, out_space);
1718 else if (label == MSG_ptn_uuid) 1721 else if (label == MSG_ptn_uuid)
1719 strlcpy(out, p->gp_id, out_space); 1722 strlcpy(out, p->gp_id, out_space);
1720 else if (label == MSG_ptn_gpt_type) { 1723 else if (label == MSG_ptn_gpt_type) {
1721 if (p->gp_type != NULL) 1724 if (p->gp_type != NULL)
1722 strlcpy(out, p->gp_type->gent.description, out_space); 1725 strlcpy(out, p->gp_type->gent.description, out_space);
1723 else if (out_space > 1) 1726 else if (out_space > 1)
1724 out[0] = 0; 1727 out[0] = 0;
1725 } else if (label == MSG_ptn_boot) 1728 } else if (label == MSG_ptn_boot)
1726 strlcpy(out, msg_string(p->gp_attr & GPT_ATTR_BOOT ? 1729 strlcpy(out, msg_string(p->gp_attr & GPT_ATTR_BOOT ?
1727 MSG_Yes : MSG_No), out_space); 1730 MSG_Yes : MSG_No), out_space);
1728 else 1731 else
1729 return false; 1732 return false;
1730 1733
1731 return true; 1734 return true;
1732} 1735}
1733 1736
1734static bool 1737static bool
1735gpt_custom_attribute_toggle(struct disk_partitions *arg, 1738gpt_custom_attribute_toggle(struct disk_partitions *arg,
1736 part_id ptn, size_t attr_no) 1739 part_id ptn, size_t attr_no)
1737{ 1740{
1738 const struct gpt_disk_partitions *parts = 1741 const struct gpt_disk_partitions *parts =
1739 (const struct gpt_disk_partitions*)arg; 1742 (const struct gpt_disk_partitions*)arg;
1740 size_t i; 1743 size_t i;
1741 struct gpt_part_entry *p; 1744 struct gpt_part_entry *p;
1742 1745
1743 for (i = 0, p = parts->partitions; p != NULL; i++, p = p->gp_next) 1746 for (i = 0, p = parts->partitions; p != NULL; i++, p = p->gp_next)
1744 if (i == ptn) 1747 if (i == ptn)
1745 break; 1748 break;
1746 1749
1747 if (p == NULL) 1750 if (p == NULL)
1748 return false; 1751 return false;
1749 1752
1750 if (attr_no >= parts->dp.pscheme->custom_attribute_count) 1753 if (attr_no >= parts->dp.pscheme->custom_attribute_count)
1751 return false; 1754 return false;
1752 1755
1753 const msg label = parts->dp.pscheme->custom_attributes[attr_no].label; 1756 const msg label = parts->dp.pscheme->custom_attributes[attr_no].label;
1754 if (label != MSG_ptn_boot) 1757 if (label != MSG_ptn_boot)
1755 return false; 1758 return false;
1756 1759
1757 if (p->gp_attr & GPT_ATTR_BOOT) { 1760 if (p->gp_attr & GPT_ATTR_BOOT) {
1758 p->gp_attr &= ~GPT_ATTR_BOOT; 1761 p->gp_attr &= ~GPT_ATTR_BOOT;
1759 } else { 1762 } else {
1760 for (i = 0, p = parts->partitions; p != NULL; 1763 for (i = 0, p = parts->partitions; p != NULL;
1761 i++, p = p->gp_next) 1764 i++, p = p->gp_next)
1762 if (i == ptn) 1765 if (i == ptn)
1763 p->gp_attr |= GPT_ATTR_BOOT; 1766 p->gp_attr |= GPT_ATTR_BOOT;
1764 else 1767 else
1765 p->gp_attr &= ~GPT_ATTR_BOOT; 1768 p->gp_attr &= ~GPT_ATTR_BOOT;
1766 } 1769 }
1767 return true; 1770 return true;
1768} 1771}
1769 1772
1770static bool 1773static bool
1771gpt_custom_attribute_set_str(struct disk_partitions *arg, 1774gpt_custom_attribute_set_str(struct disk_partitions *arg,
1772 part_id ptn, size_t attr_no, const char *new_val) 1775 part_id ptn, size_t attr_no, const char *new_val)
1773{ 1776{
1774 const struct gpt_disk_partitions *parts = 1777 const struct gpt_disk_partitions *parts =
1775 (const struct gpt_disk_partitions*)arg; 1778 (const struct gpt_disk_partitions*)arg;
1776 size_t i; 1779 size_t i;
1777 struct gpt_part_entry *p; 1780 struct gpt_part_entry *p;
1778 1781
1779 for (i = 0, p = parts->partitions; p != NULL; i++, p = p->gp_next) 1782 for (i = 0, p = parts->partitions; p != NULL; i++, p = p->gp_next)
1780 if (i == ptn) 1783 if (i == ptn)
1781 break; 1784 break;
1782 1785
1783 if (p == NULL) 1786 if (p == NULL)
1784 return false; 1787 return false;
1785 1788
1786 if (attr_no >= parts->dp.pscheme->custom_attribute_count) 1789 if (attr_no >= parts->dp.pscheme->custom_attribute_count)
1787 return false; 1790 return false;
1788 1791
1789 const msg label = parts->dp.pscheme->custom_attributes[attr_no].label; 1792 const msg label = parts->dp.pscheme->custom_attributes[attr_no].label;
1790 1793
1791 if (label != MSG_ptn_label) 1794 if (label != MSG_ptn_label)
1792 return false; 1795 return false;
1793 1796
1794 strlcpy(p->gp_label, new_val, sizeof(p->gp_label)); 1797 strlcpy(p->gp_label, new_val, sizeof(p->gp_label));
1795 return true; 1798 return true;
1796} 1799}
1797 1800
1798static bool 1801static bool
1799gpt_have_boot_support(const char *disk) 1802gpt_have_boot_support(const char *disk)
1800{ 1803{
1801#ifdef HAVE_GPT_BOOT 1804#ifdef HAVE_GPT_BOOT
1802 return true; 1805 return true;
1803#else 1806#else
1804 return false; 1807 return false;
1805#endif 1808#endif
1806} 1809}
1807 1810
1808const struct disk_part_custom_attribute gpt_custom_attrs[] = { 1811const struct disk_part_custom_attribute gpt_custom_attrs[] = {
1809 { .label = MSG_ptn_label, .type = pet_str }, 1812 { .label = MSG_ptn_label, .type = pet_str },
1810 { .label = MSG_ptn_uuid, .type = pet_str }, 1813 { .label = MSG_ptn_uuid, .type = pet_str },
1811 { .label = MSG_ptn_gpt_type, .type = pet_str }, 1814 { .label = MSG_ptn_gpt_type, .type = pet_str },
1812 { .label = MSG_ptn_boot, .type = pet_bool }, 1815 { .label = MSG_ptn_boot, .type = pet_bool },
1813}; 1816};
1814 1817
1815const struct disk_partitioning_scheme 1818const struct disk_partitioning_scheme
1816gpt_parts = { 1819gpt_parts = {
1817 .name = MSG_parttype_gpt, 1820 .name = MSG_parttype_gpt,
1818 .short_name = MSG_parttype_gpt_short, 1821 .short_name = MSG_parttype_gpt_short,
1819 .part_flag_desc = MSG_gpt_flag_desc, 1822 .part_flag_desc = MSG_gpt_flag_desc,
1820 .custom_attribute_count = __arraycount(gpt_custom_attrs), 1823 .custom_attribute_count = __arraycount(gpt_custom_attrs),
1821 .custom_attributes = gpt_custom_attrs, 1824 .custom_attributes = gpt_custom_attrs,
1822 .get_part_types_count = gpt_type_count, 1825 .get_part_types_count = gpt_type_count,
1823 .get_part_type = gpt_get_ptype, 1826 .get_part_type = gpt_get_ptype,
1824 .get_generic_part_type = gpt_get_generic_type, 1827 .get_generic_part_type = gpt_get_generic_type,
1825 .get_fs_part_type = gpt_get_fs_part_type, 1828 .get_fs_part_type = gpt_get_fs_part_type,
1826 .get_default_fstype = gpt_get_default_fstype, 1829 .get_default_fstype = gpt_get_default_fstype,
1827 .create_custom_part_type = gpt_create_custom_part_type, 1830 .create_custom_part_type = gpt_create_custom_part_type,
1828 .create_unknown_part_type = gpt_create_unknown_part_type, 1831 .create_unknown_part_type = gpt_create_unknown_part_type,
1829 .get_part_alignment = gpt_get_part_alignment, 1832 .get_part_alignment = gpt_get_part_alignment,
1830 .read_from_disk = gpt_read_from_disk, 1833 .read_from_disk = gpt_read_from_disk,
1831 .get_cylinder_size = gpt_cyl_size, 1834 .get_cylinder_size = gpt_cyl_size,
1832 .create_new_for_disk = gpt_create_new, 1835 .create_new_for_disk = gpt_create_new,
1833 .have_boot_support = gpt_have_boot_support, 1836 .have_boot_support = gpt_have_boot_support,
1834 .find_by_name = gpt_find_by_name, 1837 .find_by_name = gpt_find_by_name,
1835 .can_add_partition = gpt_can_add_partition, 1838 .can_add_partition = gpt_can_add_partition,
1836 .custom_attribute_writable = gpt_custom_attribute_writable, 1839 .custom_attribute_writable = gpt_custom_attribute_writable,
1837 .format_custom_attribute = gpt_format_custom_attribute, 1840 .format_custom_attribute = gpt_format_custom_attribute,
1838 .custom_attribute_toggle = gpt_custom_attribute_toggle, 1841 .custom_attribute_toggle = gpt_custom_attribute_toggle,
1839 .custom_attribute_set_str = gpt_custom_attribute_set_str, 1842 .custom_attribute_set_str = gpt_custom_attribute_set_str,
1840 .other_partition_identifier = gpt_get_label_str, 1843 .other_partition_identifier = gpt_get_label_str,
1841 .get_part_device = gpt_get_part_device, 1844 .get_part_device = gpt_get_part_device,
1842 .max_free_space_at = gpt_max_free_space_at, 1845 .max_free_space_at = gpt_max_free_space_at,
1843 .get_free_spaces = gpt_get_free_spaces, 1846 .get_free_spaces = gpt_get_free_spaces,
1844 .adapt_foreign_part_info = generic_adapt_foreign_part_info, 1847 .adapt_foreign_part_info = generic_adapt_foreign_part_info,
1845 .get_part_info = gpt_get_part_info, 1848 .get_part_info = gpt_get_part_info,
1846 .get_part_attr_str = gpt_get_part_attr_str, 1849 .get_part_attr_str = gpt_get_part_attr_str,
1847 .set_part_info = gpt_set_part_info, 1850 .set_part_info = gpt_set_part_info,
1848 .add_partition = gpt_add_part, 1851 .add_partition = gpt_add_part,
1849 .delete_all_partitions = gpt_delete_all_partitions, 1852 .delete_all_partitions = gpt_delete_all_partitions,
1850 .delete_partition = gpt_delete_partition, 1853 .delete_partition = gpt_delete_partition,
1851 .write_to_disk = gpt_write_to_disk, 1854 .write_to_disk = gpt_write_to_disk,
1852 .free = gpt_free, 1855 .free = gpt_free,
1853 .destroy_part_scheme = gpt_destroy_part_scheme, 1856 .destroy_part_scheme = gpt_destroy_part_scheme,
1854 .cleanup = gpt_cleanup, 1857 .cleanup = gpt_cleanup,
1855}; 1858};

cvs diff -r1.51 -r1.52 src/usr.sbin/sysinst/partman.c (switch to unified diff)

--- src/usr.sbin/sysinst/partman.c 2021/01/31 22:45:46 1.51
+++ src/usr.sbin/sysinst/partman.c 2021/07/17 11:32:50 1.52
@@ -1,1000 +1,1000 @@ @@ -1,1000 +1,1000 @@
1/* $NetBSD: partman.c,v 1.51 2021/01/31 22:45:46 rillig Exp $ */ 1/* $NetBSD: partman.c,v 1.52 2021/07/17 11:32:50 martin Exp $ */
2 2
3/* 3/*
4 * Copyright 2012 Eugene Lozovoy 4 * Copyright 2012 Eugene Lozovoy
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of Eugene Lozovoy may not be used to endorse 15 * 3. The name of Eugene Lozovoy may not be used to endorse
16 * or promote products derived from this software without specific prior 16 * or promote products derived from this software without specific prior
17 * written permission. 17 * written permission.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS'' 19 * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE 22 * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
29 * THE POSSIBILITY OF SUCH DAMAGE. 29 * THE POSSIBILITY OF SUCH DAMAGE.
30 * 30 *
31 */ 31 */
32 32
33/* 33/*
34 * Copyright 2010 The NetBSD Foundation, Inc. 34 * Copyright 2010 The NetBSD Foundation, Inc.
35 * All rights reserved. 35 * All rights reserved.
36 * 36 *
37 * Redistribution and use in source and binary forms, with or without 37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions 38 * modification, are permitted provided that the following conditions
39 * are met: 39 * are met:
40 * 1. Redistributions of source code must retain the above copyright 40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer. 41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright 42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the 43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution. 44 * documentation and/or other materials provided with the distribution.
45 * 45 *
46 * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS'' 46 * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
47 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 47 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49 * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE 49 * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
50 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 50 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
51 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 51 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
52 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 52 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
53 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 53 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
54 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 54 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
55 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 55 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
56 * THE POSSIBILITY OF SUCH DAMAGE. 56 * THE POSSIBILITY OF SUCH DAMAGE.
57 * 57 *
58 */ 58 */
59 59
60/* partman.c - extended partitioning */ 60/* partman.c - extended partitioning */
61 61
62#include <assert.h> 62#include <assert.h>
63#include <fcntl.h> 63#include <fcntl.h>
64#include <errno.h> 64#include <errno.h>
65#include <libgen.h> 65#include <libgen.h>
66#include <paths.h> 66#include <paths.h>
67#include <stdio.h> 67#include <stdio.h>
68#include <stdlib.h> 68#include <stdlib.h>
69#include <unistd.h> 69#include <unistd.h>
70#include <util.h> 70#include <util.h>
71 71
72#include "defs.h" 72#include "defs.h"
73#include "msg_defs.h" 73#include "msg_defs.h"
74#include "menu_defs.h" 74#include "menu_defs.h"
75 75
76/* XXX: replace all MAX_* defines with vars that depend on kernel settings */ 76/* XXX: replace all MAX_* defines with vars that depend on kernel settings */
77#define MAX_ENTRIES 96 77#define MAX_ENTRIES 96
78 78
79#define MAX_RAID 8 79#define MAX_RAID 8
80#define MAX_IN_RAID 48 80#define MAX_IN_RAID 48
81struct raid_comp { 81struct raid_comp {
82 char name[SSTRSIZE]; /* display name for this component */ 82 char name[SSTRSIZE]; /* display name for this component */
83 struct disk_partitions *parts; /* where is this on? */ 83 struct disk_partitions *parts; /* where is this on? */
84 part_id id; /* which partition in parts */ 84 part_id id; /* which partition in parts */
85 bool is_spare; /* is this a spare component? */ 85 bool is_spare; /* is this a spare component? */
86}; 86};
87struct raid_desc { 87struct raid_desc {
88 int enabled; 88 int enabled;
89 int blocked; 89 int blocked;
90 int node; /* the N in raid${N} */ 90 int node; /* the N in raid${N} */
91 int numRow, numCol, numSpare; 91 int numRow, numCol, numSpare;
92 int sectPerSU, SUsPerParityUnit, SUsPerReconUnit, raid_level; 92 int sectPerSU, SUsPerParityUnit, SUsPerReconUnit, raid_level;
93 daddr_t total_size; 93 daddr_t total_size;
94 struct raid_comp comp[MAX_IN_RAID]; 94 struct raid_comp comp[MAX_IN_RAID];
95}; 95};
96struct raid_desc *raids; 96struct raid_desc *raids;
97 97
98#define MAX_VND 4 98#define MAX_VND 4
99struct vnd_desc { 99struct vnd_desc {
100 int enabled; 100 int enabled;
101 int blocked; 101 int blocked;
102 int node; /* the N in vnd${N} */ 102 int node; /* the N in vnd${N} */
103 char filepath[STRSIZE]; 103 char filepath[STRSIZE];
104 daddr_t size; 104 daddr_t size;
105 int readonly; 105 int readonly;
106 int is_exist; 106 int is_exist;
107 int manual_geom; 107 int manual_geom;
108 int secsize, nsectors, ntracks, ncylinders; 108 int secsize, nsectors, ntracks, ncylinders;
109 struct pm_devs *pm; /* device this is on */ 109 struct pm_devs *pm; /* device this is on */
110 part_id pm_part; /* which partition (in pm->parts) */ 110 part_id pm_part; /* which partition (in pm->parts) */
111}; 111};
112struct vnd_desc *vnds; 112struct vnd_desc *vnds;
113 113
114#define MAX_CGD 4 114#define MAX_CGD 4
115struct cgd_desc { 115struct cgd_desc {
116 int enabled; 116 int enabled;
117 int blocked; 117 int blocked;
118 int node; /* the N in cgd${N} */ 118 int node; /* the N in cgd${N} */
119 char pm_name[SSTRSIZE]; 119 char pm_name[SSTRSIZE];
120 const char *keygen_type; 120 const char *keygen_type;
121 const char *verify_type; 121 const char *verify_type;
122 const char *enc_type; 122 const char *enc_type;
123 const char *iv_type; 123 const char *iv_type;
124 int key_size; 124 int key_size;
125 struct pm_devs *pm; /* device this is on */ 125 struct pm_devs *pm; /* device this is on */
126 part_id pm_part; /* which partition (in pm->parts) */ 126 part_id pm_part; /* which partition (in pm->parts) */
127}; 127};
128struct cgd_desc *cgds; 128struct cgd_desc *cgds;
129 129
130#define MAX_LVM_VG 16 130#define MAX_LVM_VG 16
131#define MAX_LVM_PV 255 131#define MAX_LVM_PV 255
132#define MAX_LVM_LV 255 132#define MAX_LVM_LV 255
133 133
134struct lvm_pv_reg { 134struct lvm_pv_reg {
135 struct pm_devs *pm; 135 struct pm_devs *pm;
136 daddr_t start; 136 daddr_t start;
137}; 137};
138struct lvm_pv_reg lvm_pvs[MAX_LVM_PV]; /* XXX - make dynamic */ 138struct lvm_pv_reg lvm_pvs[MAX_LVM_PV]; /* XXX - make dynamic */
139 139
140typedef struct pv_t { 140typedef struct pv_t {
141 struct pm_devs *pm; 141 struct pm_devs *pm;
142 char pm_name[SSTRSIZE]; 142 char pm_name[SSTRSIZE];
143 part_id pm_part; 143 part_id pm_part;
144 int metadatasize; 144 int metadatasize;
145 int metadatacopies; 145 int metadatacopies;
146 int labelsector; 146 int labelsector;
147 int setphysicalvolumesize; 147 int setphysicalvolumesize;
148} pv_t; 148} pv_t;
149typedef struct lv_t { 149typedef struct lv_t {
150 int blocked; 150 int blocked;
151 daddr_t size; 151 daddr_t size;
152 char name[SSTRSIZE]; 152 char name[SSTRSIZE];
153 int readonly; 153 int readonly;
154 int contiguous; 154 int contiguous;
155 char extents[SSTRSIZE]; 155 char extents[SSTRSIZE];
156 int minor; 156 int minor;
157 int mirrors; 157 int mirrors;
158 int regionsize; 158 int regionsize;
159 int persistent; 159 int persistent;
160 int readahead; 160 int readahead;
161 int stripes; 161 int stripes;
162 int stripesize; 162 int stripesize;
163 int zero; 163 int zero;
164} lv_t; 164} lv_t;
165typedef struct lvms_t { 165typedef struct lvms_t {
166 int enabled; 166 int enabled;
167 int blocked; 167 int blocked;
168 char name[SSTRSIZE]; 168 char name[SSTRSIZE];
169 int maxlogicalvolumes; 169 int maxlogicalvolumes;
170 int maxphysicalvolumes; 170 int maxphysicalvolumes;
171 int physicalextentsize; 171 int physicalextentsize;
172 daddr_t total_size; 172 daddr_t total_size;
173 pv_t pv[MAX_LVM_PV]; 173 pv_t pv[MAX_LVM_PV];
174 lv_t lv[MAX_LVM_LV]; 174 lv_t lv[MAX_LVM_LV];
175} lvms_t; 175} lvms_t;
176lvms_t *lvms; 176lvms_t *lvms;
177 177
178typedef struct structinfo_t { 178typedef struct structinfo_t {
179 int max; 179 int max;
180 uint entry_size; 180 uint entry_size;
181 uint parent_size; 181 uint parent_size;
182 void *entry_first; 182 void *entry_first;
183 void *entry_enabled; 183 void *entry_enabled;
184 void *entry_blocked; 184 void *entry_blocked;
185 void *entry_node; 185 void *entry_node;
186} structinfo_t; 186} structinfo_t;
187structinfo_t raids_t_info, vnds_t_info, cgds_t_info, lvms_t_info, lv_t_info; 187structinfo_t raids_t_info, vnds_t_info, cgds_t_info, lvms_t_info, lv_t_info;
188 188
189typedef struct pm_upddevlist_adv_t { 189typedef struct pm_upddevlist_adv_t {
190 const char *create_msg; 190 const char *create_msg;
191 int pe_type; 191 int pe_type;
192 structinfo_t *s; 192 structinfo_t *s;
193 int sub_num; 193 int sub_num;
194 struct pm_upddevlist_adv_t *sub; 194 struct pm_upddevlist_adv_t *sub;
195} pm_upddevlist_adv_t; 195} pm_upddevlist_adv_t;
196 196
197#define MAX_MNTS 48 197#define MAX_MNTS 48
198struct { 198struct {
199 char dev[STRSIZE]; 199 char dev[STRSIZE];
200 const char *mnt_opts, *on; 200 const char *mnt_opts, *on;
201} *mnts; 201} *mnts;
202 202
203static int pm_cursel; /* Number of selected entry in main menu */ 203static int pm_cursel; /* Number of selected entry in main menu */
204static int pm_changed; /* flag indicating that we have unsaved changes */ 204static int pm_changed; /* flag indicating that we have unsaved changes */
205static int pm_raid_curspare; /* XXX: replace by true way */ 205static int pm_raid_curspare; /* XXX: replace by true way */
206static int pm_retvalue; 206static int pm_retvalue;
207 207
208enum { /* RAIDframe menu enum */ 208enum { /* RAIDframe menu enum */
209 PMR_MENU_DEVS, PMR_MENU_DEVSSPARE, PMR_MENU_RAIDLEVEL, PMR_MENU_NUMROW, 209 PMR_MENU_DEVS, PMR_MENU_DEVSSPARE, PMR_MENU_RAIDLEVEL, PMR_MENU_NUMROW,
210 PMR_MENU_NUMCOL, PMR_MENU_NUMSPARE, PMR_MENU_SECTPERSU, PMR_MENU_SUSPERPARITYUNIT, 210 PMR_MENU_NUMCOL, PMR_MENU_NUMSPARE, PMR_MENU_SECTPERSU, PMR_MENU_SUSPERPARITYUNIT,
211 PMR_MENU_SUSPERRECONUNIT, PMR_MENU_REMOVE, PMR_MENU_END 211 PMR_MENU_SUSPERRECONUNIT, PMR_MENU_REMOVE, PMR_MENU_END
212}; 212};
213 213
214enum { /* VND menu enum */ 214enum { /* VND menu enum */
215 PMV_MENU_FILEPATH, PMV_MENU_EXIST, PMV_MENU_SIZE, PMV_MENU_RO, PMV_MENU_MGEOM, 215 PMV_MENU_FILEPATH, PMV_MENU_EXIST, PMV_MENU_SIZE, PMV_MENU_RO, PMV_MENU_MGEOM,
216 PMV_MENU_SECSIZE, PMV_MENU_NSECTORS, PMV_MENU_NTRACKS, PMV_MENU_NCYLINDERS, 216 PMV_MENU_SECSIZE, PMV_MENU_NSECTORS, PMV_MENU_NTRACKS, PMV_MENU_NCYLINDERS,
217 PMV_MENU_REMOVE, PMV_MENU_END 217 PMV_MENU_REMOVE, PMV_MENU_END
218}; 218};
219 219
220enum { /* CGD menu enum */ 220enum { /* CGD menu enum */
221 PMC_MENU_DEV, PMC_MENU_ENCTYPE, PMC_MENU_KEYSIZE, PMC_MENU_IVTYPE, 221 PMC_MENU_DEV, PMC_MENU_ENCTYPE, PMC_MENU_KEYSIZE, PMC_MENU_IVTYPE,
222 PMC_MENU_KEYGENTYPE, PMC_MENU_VERIFYTYPE, PMC_MENU_REMOVE, PMC_MENU_END 222 PMC_MENU_KEYGENTYPE, PMC_MENU_VERIFYTYPE, PMC_MENU_REMOVE, PMC_MENU_END
223}; 223};
224 224
225enum { /* LVM menu enum */ 225enum { /* LVM menu enum */
226 PML_MENU_PV, PML_MENU_NAME, PML_MENU_MAXLOGICALVOLUMES, 226 PML_MENU_PV, PML_MENU_NAME, PML_MENU_MAXLOGICALVOLUMES,
227 PML_MENU_MAXPHYSICALVOLUMES, PML_MENU_PHYSICALEXTENTSIZE, 227 PML_MENU_MAXPHYSICALVOLUMES, PML_MENU_PHYSICALEXTENTSIZE,
228 PML_MENU_REMOVE, PML_MENU_END 228 PML_MENU_REMOVE, PML_MENU_END
229}; 229};
230 230
231enum { /* LVM submenu (logical volumes) enum */ 231enum { /* LVM submenu (logical volumes) enum */
232 PMLV_MENU_NAME, PMLV_MENU_SIZE, PMLV_MENU_READONLY, PMLV_MENU_CONTIGUOUS, 232 PMLV_MENU_NAME, PMLV_MENU_SIZE, PMLV_MENU_READONLY, PMLV_MENU_CONTIGUOUS,
233 PMLV_MENU_EXTENTS, PMLV_MENU_MINOR, PMLV_MENU_PERSISTENT, 233 PMLV_MENU_EXTENTS, PMLV_MENU_MINOR, PMLV_MENU_PERSISTENT,
234 PMLV_MENU_MIRRORS, PMLV_MENU_REGIONSIZE, PMLV_MENU_READAHEAD, 234 PMLV_MENU_MIRRORS, PMLV_MENU_REGIONSIZE, PMLV_MENU_READAHEAD,
235 PMLV_MENU_STRIPES, PMLV_MENU_STRIPESIZE, PMLV_MENU_ZERO, 235 PMLV_MENU_STRIPES, PMLV_MENU_STRIPESIZE, PMLV_MENU_ZERO,
236 PMLV_MENU_REMOVE, PMLV_MENU_END 236 PMLV_MENU_REMOVE, PMLV_MENU_END
237}; 237};
238 238
239struct part_entry pm_dev_list(int); 239struct part_entry pm_dev_list(int);
240static int pm_raid_disk_add(menudesc *, void *); 240static int pm_raid_disk_add(menudesc *, void *);
241static int pm_raid_disk_del(menudesc *, void *); 241static int pm_raid_disk_del(menudesc *, void *);
242static int pm_cgd_disk_set(struct cgd_desc *, struct part_entry *); 242static int pm_cgd_disk_set(struct cgd_desc *, struct part_entry *);
243static int pm_mount(struct pm_devs *, int); 243static int pm_mount(struct pm_devs *, int);
244static int pm_upddevlist(menudesc *, void *); 244static int pm_upddevlist(menudesc *, void *);
245static void pm_select(struct pm_devs *); 245static void pm_select(struct pm_devs *);
246 246
247static void 247static void
248pm_edit_size_value(msg prompt_msg, daddr_t bps, daddr_t cylsec, daddr_t *size) 248pm_edit_size_value(msg prompt_msg, daddr_t bps, daddr_t cylsec, daddr_t *size)
249{ 249{
250 250
251 char answer[16], dflt[16]; 251 char answer[16], dflt[16];
252 daddr_t new_size_val, mult; 252 daddr_t new_size_val, mult;
253 253
254 snprintf(dflt, sizeof dflt, "%" PRIu64 "%s", *size / sizemult, 254 snprintf(dflt, sizeof dflt, "%" PRIu64 "%s", *size / sizemult,
255 multname); 255 multname);
256 256
257 msg_prompt_win(prompt_msg, -1, 18, 0, 0, dflt, answer, sizeof answer); 257 msg_prompt_win(prompt_msg, -1, 18, 0, 0, dflt, answer, sizeof answer);
258 258
259 mult = sizemult; 259 mult = sizemult;
260 new_size_val = parse_disk_pos(answer, &mult, bps, cylsec, NULL); 260 new_size_val = parse_disk_pos(answer, &mult, bps, cylsec, NULL);
261 261
262 if (new_size_val > 0) 262 if (new_size_val > 0)
263 *size = new_size_val * mult; 263 *size = new_size_val * mult;
264} 264}
265 265
266static const char * 266static const char *
267pm_get_mount(struct pm_devs *p, part_id id) 267pm_get_mount(struct pm_devs *p, part_id id)
268{ 268{
269 269
270 if (p->mounted == NULL) 270 if (p->mounted == NULL)
271 return NULL; 271 return NULL;
272 if (id >= p->parts->num_part) 272 if (id >= p->parts->num_part)
273 return NULL; 273 return NULL;
274 return p->mounted[id]; 274 return p->mounted[id];
275} 275}
276 276
277bool pm_set_mount(struct pm_devs *p, part_id id, const char *path); 277bool pm_set_mount(struct pm_devs *p, part_id id, const char *path);
278 278
279bool 279bool
280pm_set_mount(struct pm_devs *p, part_id id, const char *path) 280pm_set_mount(struct pm_devs *p, part_id id, const char *path)
281{ 281{
282 282
283 if (p->parts == NULL || id >= p->parts->num_part) 283 if (p->parts == NULL || id >= p->parts->num_part)
284 return false; 284 return false;
285 285
286 if (p->mounted == NULL) { 286 if (p->mounted == NULL) {
287 p->mounted = calloc(p->parts->num_part, sizeof(char*)); 287 p->mounted = calloc(p->parts->num_part, sizeof(char*));
288 if (p->mounted == NULL) 288 if (p->mounted == NULL)
289 return false; 289 return false;
290 } 290 }
291 free(p->mounted[id]); 291 free(p->mounted[id]);
292 p->mounted[id] = strdup(path); 292 p->mounted[id] = strdup(path);
293 return p->mounted[id] != NULL; 293 return p->mounted[id] != NULL;
294} 294}
295 295
296/* Universal menu for RAID/VND/CGD/LVM entry edit */ 296/* Universal menu for RAID/VND/CGD/LVM entry edit */
297static int 297static int
298pm_edit(int menu_entries_count, void (*menu_fmt)(menudesc *, int, void *), 298pm_edit(int menu_entries_count, void (*menu_fmt)(menudesc *, int, void *),
299 int (*action)(menudesc *, void *), int (*check_fun)(void *), 299 int (*action)(menudesc *, void *), int (*check_fun)(void *),
300 void (*entry_init)(void *, void *), void *entry_init_arg, 300 void (*entry_init)(void *, void *), void *entry_init_arg,
301 void *dev_ptr, int dev_ptr_delta, structinfo_t *s) 301 void *dev_ptr, int dev_ptr_delta, structinfo_t *s)
302{ 302{
303 int i, ok = 0; 303 int i, ok = 0;
304 menu_ent *menu_entries; 304 menu_ent *menu_entries;
305 305
306 if (dev_ptr == NULL) { 306 if (dev_ptr == NULL) {
307 /* We should create new device */ 307 /* We should create new device */
308 for (i = 0; i < s->max && !ok; i++) 308 for (i = 0; i < s->max && !ok; i++)
309 if (*(int*)((char*)s->entry_enabled + dev_ptr_delta + s->entry_size * i) == 0) { 309 if (*(int*)((char*)s->entry_enabled + dev_ptr_delta + s->entry_size * i) == 0) {
310 dev_ptr = (char*)s->entry_first + dev_ptr_delta + s->entry_size * i; 310 dev_ptr = (char*)s->entry_first + dev_ptr_delta + s->entry_size * i;
311 entry_init(dev_ptr, entry_init_arg); 311 entry_init(dev_ptr, entry_init_arg);
312 ok = 1; 312 ok = 1;
313 } 313 }
314 if (!ok) { 314 if (!ok) {
315 /* We do not have free device slots */ 315 /* We do not have free device slots */
316 hit_enter_to_continue(NULL, MSG_limitcount); 316 hit_enter_to_continue(NULL, MSG_limitcount);
317 return -1; 317 return -1;
318 } 318 }
319 } 319 }
320 320
321 menu_entries = calloc(menu_entries_count, sizeof *menu_entries); 321 menu_entries = calloc(menu_entries_count, sizeof *menu_entries);
322 for (i = 0; i < menu_entries_count - 1; i++) 322 for (i = 0; i < menu_entries_count - 1; i++)
323 menu_entries[i] = (menu_ent) { .opt_action=action }; 323 menu_entries[i] = (menu_ent) { .opt_action=action };
324 menu_entries[i] = (menu_ent) { .opt_name=MSG_fremove, 324 menu_entries[i] = (menu_ent) { .opt_name=MSG_fremove,
325 .opt_flags=OPT_EXIT, 325 .opt_flags=OPT_EXIT,
326 .opt_action=action }; 326 .opt_action=action };
327 327
328 int menu_no = -1; 328 int menu_no = -1;
329 menu_no = new_menu(NULL, menu_entries, menu_entries_count, 329 menu_no = new_menu(NULL, menu_entries, menu_entries_count,
330 -1, -1, 0, 40, MC_NOCLEAR | MC_SCROLL, 330 -1, -1, 0, 40, MC_NOCLEAR | MC_SCROLL,
331 NULL, menu_fmt, NULL, NULL, MSG_DONE); 331 NULL, menu_fmt, NULL, NULL, MSG_DONE);
332 332
333 process_menu(menu_no, dev_ptr); 333 process_menu(menu_no, dev_ptr);
334 free_menu(menu_no); 334 free_menu(menu_no);
335 free(menu_entries); 335 free(menu_entries);
336 336
337 return check_fun(dev_ptr); 337 return check_fun(dev_ptr);
338} 338}
339 339
340/* Show filtered partitions menu */ 340/* Show filtered partitions menu */
341struct part_entry 341struct part_entry
342pm_dev_list(int type) 342pm_dev_list(int type)
343{ 343{
344 int dev_num = -1, num_devs = 0; 344 int dev_num = -1, num_devs = 0;
345 bool ok; 345 bool ok;
346 part_id i; 346 part_id i;
347 int menu_no; 347 int menu_no;
348 struct disk_part_info info; 348 struct disk_part_info info;
349 menu_ent menu_entries[MAX_DISKS*MAXPARTITIONS]; 349 menu_ent menu_entries[MAX_DISKS*MAXPARTITIONS];
350 struct part_entry disk_entries[MAX_DISKS*MAXPARTITIONS]; 350 struct part_entry disk_entries[MAX_DISKS*MAXPARTITIONS];
351 struct pm_devs *pm_i; 351 struct pm_devs *pm_i;
352 352
353 SLIST_FOREACH(pm_i, &pm_head, l) { 353 SLIST_FOREACH(pm_i, &pm_head, l) {
354 if (pm_i->parts == NULL) 354 if (pm_i->parts == NULL)
355 continue; 355 continue;
356 for (i = 0; i < pm_i->parts->num_part; i++) { 356 for (i = 0; i < pm_i->parts->num_part; i++) {
357 ok = false; 357 ok = false;
358 if (!pm_i->parts->pscheme->get_part_info(pm_i->parts, 358 if (!pm_i->parts->pscheme->get_part_info(pm_i->parts,
359 i, &info)) 359 i, &info))
360 continue; 360 continue;
361 if (info.flags & 361 if (info.flags &
362 (PTI_WHOLE_DISK|PTI_PSCHEME_INTERNAL|PTI_RAW_PART)) 362 (PTI_WHOLE_DISK|PTI_PSCHEME_INTERNAL|PTI_RAW_PART))
363 continue; 363 continue;
364 switch (type) { 364 switch (type) {
365 case PM_RAID: 365 case PM_RAID:
366 if (info.fs_type == FS_RAID) 366 if (info.fs_type == FS_RAID)
367 ok = 1; 367 ok = 1;
368 break; 368 break;
369 case PM_CGD: 369 case PM_CGD:
370 if (info.fs_type == FS_CGD) 370 if (info.fs_type == FS_CGD)
371 ok = 1; 371 ok = 1;
372 break; 372 break;
373 case PM_LVM: 373 case PM_LVM:
374 if (pm_is_lvmpv(pm_i, i, &info)) 374 if (pm_is_lvmpv(pm_i, i, &info))
375 ok = 1; 375 ok = 1;
376 break; 376 break;
377 } 377 }
378 if (!ok) 378 if (!ok)
379 continue; 379 continue;
380 if (pm_partusage(pm_i, i, 0) != 0) 380 if (pm_partusage(pm_i, i, 0) != 0)
381 continue; 381 continue;
382 382
383 disk_entries[num_devs].dev_ptr = pm_i; 383 disk_entries[num_devs].dev_ptr = pm_i;
384 disk_entries[num_devs].id = i; 384 disk_entries[num_devs].id = i;
385 disk_entries[num_devs].parts = pm_i->parts; 385 disk_entries[num_devs].parts = pm_i->parts;
386 386
387 pm_i->parts->pscheme->get_part_device( 387 pm_i->parts->pscheme->get_part_device(
388 pm_i->parts, i, disk_entries[num_devs].fullname, 388 pm_i->parts, i, disk_entries[num_devs].fullname,
389 sizeof disk_entries[num_devs].fullname, 389 sizeof disk_entries[num_devs].fullname,
390 NULL, plain_name, false, true); 390 NULL, plain_name, false, true);
391 391
392 menu_entries[num_devs] = (struct menu_ent) { 392 menu_entries[num_devs] = (struct menu_ent) {
393 .opt_name = disk_entries[num_devs].fullname, 393 .opt_name = disk_entries[num_devs].fullname,
394 .opt_action = set_menu_select, 394 .opt_action = set_menu_select,
395 .opt_flags = OPT_EXIT, 395 .opt_flags = OPT_EXIT,
396 }; 396 };
397 num_devs++; 397 num_devs++;
398 } 398 }
399 } 399 }
400 400
401 menu_no = new_menu(MSG_avdisks, 401 menu_no = new_menu(MSG_avdisks,
402 menu_entries, num_devs, -1, -1, 402 menu_entries, num_devs, -1, -1,
403 (num_devs+1<3)?3:num_devs+1, 13, 403 (num_devs+1<3)?3:num_devs+1, 13,
404 MC_SCROLL | MC_NOCLEAR, NULL, NULL, NULL, NULL, MSG_cancel); 404 MC_SCROLL | MC_NOCLEAR, NULL, NULL, NULL, NULL, MSG_cancel);
405 if (menu_no == -1) 405 if (menu_no == -1)
406 return (struct part_entry) { }; 406 return (struct part_entry) { };
407 process_menu(menu_no, &dev_num); 407 process_menu(menu_no, &dev_num);
408 free_menu(menu_no); 408 free_menu(menu_no);
409 409
410 if (dev_num < 0 || dev_num >= num_devs) 410 if (dev_num < 0 || dev_num >= num_devs)
411 return (struct part_entry) { }; 411 return (struct part_entry) { };
412 412
413 pm_retvalue = dev_num; 413 pm_retvalue = dev_num;
414 return disk_entries[dev_num]; 414 return disk_entries[dev_num];
415} 415}
416 416
417/* Get unused raid*, cgd* or vnd* device */ 417/* Get unused raid*, cgd* or vnd* device */
418static int 418static int
419pm_manage_getfreenode(void *node, const char *d, structinfo_t *s) 419pm_manage_getfreenode(void *node, const char *d, structinfo_t *s)
420{ 420{
421 int i, ii, ok; 421 int i, ii, ok;
422 char buf[SSTRSIZE]; 422 char buf[SSTRSIZE];
423 struct pm_devs *pm_i; 423 struct pm_devs *pm_i;
424 424
425 *(int*)node = -1; 425 *(int*)node = -1;
426 for (i = 0; i < s->max; i++) { 426 for (i = 0; i < s->max; i++) {
427 ok = 1; 427 ok = 1;
428 /* Check that node is not already reserved */ 428 /* Check that node is not already reserved */
429 for (ii = 0; ii < s->max; ii++) { 429 for (ii = 0; ii < s->max; ii++) {
430 if (*(int*)((char*)s->entry_enabled + s->entry_size 430 if (*(int*)((char*)s->entry_enabled + s->entry_size
431 * ii) == 0) 431 * ii) == 0)
432 continue; 432 continue;
433 if (*(int*)((char*)s->entry_node + s->entry_size * ii) 433 if (*(int*)((char*)s->entry_node + s->entry_size * ii)
434 == i) { 434 == i) {
435 ok = 0; 435 ok = 0;
436 break; 436 break;
437 } 437 }
438 } 438 }
439 if (! ok) 439 if (! ok)
440 continue; 440 continue;
441 /* Check that node is not in the device list */ 441 /* Check that node is not in the device list */
442 snprintf(buf, SSTRSIZE, "%s%d", d, i); 442 snprintf(buf, SSTRSIZE, "%s%d", d, i);
443 SLIST_FOREACH(pm_i, &pm_head, l) 443 SLIST_FOREACH(pm_i, &pm_head, l)
444 if (! strcmp(pm_i->diskdev, buf)) { 444 if (! strcmp(pm_i->diskdev, buf)) {
445 ok = 0; 445 ok = 0;
446 break; 446 break;
447 } 447 }
448 if (ok) { 448 if (ok) {
449 *(int*)node = i; 449 *(int*)node = i;
450 return i; 450 return i;
451 } 451 }
452 } 452 }
453 hit_enter_to_continue(NULL, MSG_nofreedev); 453 hit_enter_to_continue(NULL, MSG_nofreedev);
454 return -1; 454 return -1;
455} 455}
456 456
457/* 457/*
458 * Show a line for a device, usually with full size in the right 458 * Show a line for a device, usually with full size in the right
459 * column, alternatively (if != NULL) with no_size_display 459 * column, alternatively (if != NULL) with no_size_display
460 * instead in paranthesis (used for error displays or to note 460 * instead in paranthesis (used for error displays or to note
461 * a action that can be done to this device. 461 * a action that can be done to this device.
462 */ 462 */
463static void 463static void
464pm_fmt_disk_line(WINDOW *w, const char *line, const char *on, 464pm_fmt_disk_line(WINDOW *w, const char *line, const char *on,
465 daddr_t total, const char *no_size_display) 465 daddr_t total, const char *no_size_display)
466{ 466{
467 char out[STRSIZE], human[6]; 467 char out[STRSIZE], human[6];
468 468
469 if (on != NULL) { 469 if (on != NULL) {
470 snprintf(out, sizeof out, "%s %s %s", line, 470 snprintf(out, sizeof out, "%s %s %s", line,
471 msg_string(MSG_pm_menu_on), on); 471 msg_string(MSG_pm_menu_on), on);
472 line = out; 472 line = out;
473 } 473 }
474 if (no_size_display != NULL) { 474 if (no_size_display != NULL) {
475 wprintw(w, " %-56s (%s)", line, no_size_display); 475 wprintw(w, " %-56s (%s)", line, no_size_display);
476 } else { 476 } else {
477 humanize_number(human, sizeof(human), 477 humanize_number(human, sizeof(human),
478 total * 512, "", 478 total * 512, "",
479 HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); 479 HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
480 wprintw(w, " %-56s %s", line, human); 480 wprintw(w, " %-56s %s", line, human);
481 } 481 }
482} 482}
483 483
484/*** 484/***
485 RAIDs 485 RAIDs
486 ***/ 486 ***/
487 487
488static void 488static void
489pm_raid_menufmt(menudesc *m, int opt, void *arg) 489pm_raid_menufmt(menudesc *m, int opt, void *arg)
490{ 490{
491 int i, ok = 0; 491 int i, ok = 0;
492 char buf[STRSIZE], rdev[STRSIZE], level[STRSIZE], *line; 492 char buf[STRSIZE], rdev[STRSIZE], level[STRSIZE], *line;
493 struct raid_desc *dev_ptr = ((struct part_entry *)arg)[opt].dev_ptr; 493 struct raid_desc *dev_ptr = ((struct part_entry *)arg)[opt].dev_ptr;
494 494
495 if (dev_ptr->enabled == 0) 495 if (dev_ptr->enabled == 0)
496 return; 496 return;
497 buf[0] = '\0'; 497 buf[0] = '\0';
498 sprintf(rdev, "raid%d", dev_ptr->node); 498 sprintf(rdev, "raid%d", dev_ptr->node);
499 for (i = 0; i < MAX_IN_RAID; i++) { 499 for (i = 0; i < MAX_IN_RAID; i++) {
500 if (dev_ptr->comp[i].parts != NULL) { 500 if (dev_ptr->comp[i].parts != NULL) {
501 strlcat(buf, dev_ptr->comp[i].name, sizeof buf); 501 strlcat(buf, dev_ptr->comp[i].name, sizeof buf);
502 strlcat(buf, " ", sizeof buf); 502 strlcat(buf, " ", sizeof buf);
503 ok = 1; 503 ok = 1;
504 } 504 }
505 } 505 }
506 if (ok) { 506 if (ok) {
507 sprintf(level, "%u", dev_ptr->raid_level); 507 sprintf(level, "%u", dev_ptr->raid_level);
508 const char *args[] = { rdev, level }; 508 const char *args[] = { rdev, level };
509 line = str_arg_subst(msg_string(MSG_raid_menufmt), 509 line = str_arg_subst(msg_string(MSG_raid_menufmt),
510 __arraycount(args), args); 510 __arraycount(args), args);
511 pm_fmt_disk_line(m->mw, line, buf, dev_ptr->total_size, NULL); 511 pm_fmt_disk_line(m->mw, line, buf, dev_ptr->total_size, NULL);
512 free(line); 512 free(line);
513 } else { 513 } else {
514 pm_fmt_disk_line(m->mw, buf, NULL, 0, 514 pm_fmt_disk_line(m->mw, buf, NULL, 0,
515 msg_string(MSG_raid_err_menufmt)); 515 msg_string(MSG_raid_err_menufmt));
516 } 516 }
517} 517}
518 518
519static void 519static void
520pm_raid_edit_menufmt(menudesc *m, int opt, void *arg) 520pm_raid_edit_menufmt(menudesc *m, int opt, void *arg)
521{ 521{
522 int i; 522 int i;
523 char buf[STRSIZE]; 523 char buf[STRSIZE];
524 struct raid_desc *dev_ptr = arg; 524 struct raid_desc *dev_ptr = arg;
525 525
526 buf[0] = '\0'; 526 buf[0] = '\0';
527 switch (opt) { 527 switch (opt) {
528 case PMR_MENU_DEVS: 528 case PMR_MENU_DEVS:
529 strlcpy(buf, msg_string(MSG_raid_disks_fmt), 529 strlcpy(buf, msg_string(MSG_raid_disks_fmt),
530 sizeof buf); 530 sizeof buf);
531 strlcat(buf, ": ", sizeof buf); 531 strlcat(buf, ": ", sizeof buf);
532 for (i = 0; i < MAX_IN_RAID; i++) { 532 for (i = 0; i < MAX_IN_RAID; i++) {
533 if (dev_ptr->comp[i].parts == NULL || 533 if (dev_ptr->comp[i].parts == NULL ||
534 dev_ptr->comp[i].is_spare) 534 dev_ptr->comp[i].is_spare)
535 continue; 535 continue;
536 strlcat(buf, " ", sizeof buf); 536 strlcat(buf, " ", sizeof buf);
537 strlcat(buf, dev_ptr->comp[i].name, sizeof buf); 537 strlcat(buf, dev_ptr->comp[i].name, sizeof buf);
538 } 538 }
539 wprintw(m->mw, "%s", buf); 539 wprintw(m->mw, "%s", buf);
540 break; 540 break;
541 case PMR_MENU_DEVSSPARE: 541 case PMR_MENU_DEVSSPARE:
542 strlcpy(buf, msg_string(MSG_raid_spares_fmt), 542 strlcpy(buf, msg_string(MSG_raid_spares_fmt),
543 sizeof buf); 543 sizeof buf);
544 strlcat(buf, ": ", sizeof buf); 544 strlcat(buf, ": ", sizeof buf);
545 for (i = 0; i < MAX_IN_RAID; i++) { 545 for (i = 0; i < MAX_IN_RAID; i++) {
546 if (dev_ptr->comp[i].parts == NULL || 546 if (dev_ptr->comp[i].parts == NULL ||
547 !dev_ptr->comp[i].is_spare) 547 !dev_ptr->comp[i].is_spare)
548 continue; 548 continue;
549 strlcat(buf, " ", sizeof buf); 549 strlcat(buf, " ", sizeof buf);
550 strlcat(buf, dev_ptr->comp[i].name, sizeof buf); 550 strlcat(buf, dev_ptr->comp[i].name, sizeof buf);
551 } 551 }
552 wprintw(m->mw, "%s", buf); 552 wprintw(m->mw, "%s", buf);
553 break; 553 break;
554 case PMR_MENU_RAIDLEVEL: 554 case PMR_MENU_RAIDLEVEL:
555 wprintw(m->mw, "%s: %u", 555 wprintw(m->mw, "%s: %u",
556 msg_string(MSG_raid_level_fmt), 556 msg_string(MSG_raid_level_fmt),
557 dev_ptr->raid_level); 557 dev_ptr->raid_level);
558 break; 558 break;
559 case PMR_MENU_NUMROW: 559 case PMR_MENU_NUMROW:
560 wprintw(m->mw, "%s: %u", 560 wprintw(m->mw, "%s: %u",
561 msg_string(MSG_raid_numrow_fmt), dev_ptr->numRow); 561 msg_string(MSG_raid_numrow_fmt), dev_ptr->numRow);
562 break; 562 break;
563 case PMR_MENU_NUMCOL: 563 case PMR_MENU_NUMCOL:
564 wprintw(m->mw, "%s: %u", 564 wprintw(m->mw, "%s: %u",
565 msg_string(MSG_raid_numcol_fmt), dev_ptr->numCol); 565 msg_string(MSG_raid_numcol_fmt), dev_ptr->numCol);
566 break; 566 break;
567 case PMR_MENU_NUMSPARE: 567 case PMR_MENU_NUMSPARE:
568 wprintw(m->mw, "%s: %u", 568 wprintw(m->mw, "%s: %u",
569 msg_string(MSG_raid_numspare_fmt), 569 msg_string(MSG_raid_numspare_fmt),
570 dev_ptr->numSpare); 570 dev_ptr->numSpare);
571 break; 571 break;
572 case PMR_MENU_SECTPERSU: 572 case PMR_MENU_SECTPERSU:
573 wprintw(m->mw, "%s: %u", 573 wprintw(m->mw, "%s: %u",
574 msg_string(MSG_raid_sectpersu_fmt), 574 msg_string(MSG_raid_sectpersu_fmt),
575 dev_ptr->sectPerSU); 575 dev_ptr->sectPerSU);
576 break; 576 break;
577 case PMR_MENU_SUSPERPARITYUNIT: 577 case PMR_MENU_SUSPERPARITYUNIT:
578 wprintw(m->mw, "%s: %u", 578 wprintw(m->mw, "%s: %u",
579 msg_string(MSG_raid_superpar_fmt), 579 msg_string(MSG_raid_superpar_fmt),
580 dev_ptr->SUsPerParityUnit); 580 dev_ptr->SUsPerParityUnit);
581 break; 581 break;
582 case PMR_MENU_SUSPERRECONUNIT: 582 case PMR_MENU_SUSPERRECONUNIT:
583 wprintw(m->mw, "%s: %u", 583 wprintw(m->mw, "%s: %u",
584 msg_string(MSG_raid_superrec_fmt), 584 msg_string(MSG_raid_superrec_fmt),
585 dev_ptr->SUsPerReconUnit); 585 dev_ptr->SUsPerReconUnit);
586 break; 586 break;
587 } 587 }
588} 588}
589 589
590static int 590static int
591pm_raid_set_value(menudesc *m, void *arg) 591pm_raid_set_value(menudesc *m, void *arg)
592{ 592{
593 int retvalue = -1; 593 int retvalue = -1;
594 int *out_var = NULL; 594 int *out_var = NULL;
595 char buf[SSTRSIZE]; 595 char buf[SSTRSIZE];
596 const char *msg_to_show = NULL; 596 const char *msg_to_show = NULL;
597 struct raid_desc *dev_ptr = arg; 597 struct raid_desc *dev_ptr = arg;
598 598
599 static menu_ent menuent_disk_adddel[] = { 599 static menu_ent menuent_disk_adddel[] = {
600 { .opt_name=MSG_add, .opt_flags=OPT_EXIT, 600 { .opt_name=MSG_add, .opt_flags=OPT_EXIT,
601 .opt_action=pm_raid_disk_add }, 601 .opt_action=pm_raid_disk_add },
602 { .opt_name=MSG_remove, .opt_flags=OPT_EXIT, 602 { .opt_name=MSG_remove, .opt_flags=OPT_EXIT,
603 .opt_action=pm_raid_disk_del } 603 .opt_action=pm_raid_disk_del }
604 }; 604 };
605 static int menu_disk_adddel = -1; 605 static int menu_disk_adddel = -1;
606 if (menu_disk_adddel == -1) { 606 if (menu_disk_adddel == -1) {
607 menu_disk_adddel = new_menu(NULL, menuent_disk_adddel, 607 menu_disk_adddel = new_menu(NULL, menuent_disk_adddel,
608 __arraycount(menuent_disk_adddel), 608 __arraycount(menuent_disk_adddel),
609 -1, -1, 0, 10, MC_NOCLEAR, NULL, NULL, NULL, NULL, 609 -1, -1, 0, 10, MC_NOCLEAR, NULL, NULL, NULL, NULL,
610 MSG_cancel); 610 MSG_cancel);
611 } 611 }
612 612
613 switch (m->cursel) { 613 switch (m->cursel) {
614 case PMR_MENU_DEVS: 614 case PMR_MENU_DEVS:
615 pm_raid_curspare = 0; 615 pm_raid_curspare = 0;
616 process_menu(menu_disk_adddel, dev_ptr); 616 process_menu(menu_disk_adddel, dev_ptr);
617 return 0; 617 return 0;
618 case PMR_MENU_DEVSSPARE: 618 case PMR_MENU_DEVSSPARE:
619 pm_raid_curspare = 1; 619 pm_raid_curspare = 1;
620 process_menu(menu_disk_adddel, dev_ptr); 620 process_menu(menu_disk_adddel, dev_ptr);
621 return 0; 621 return 0;
622 case PMR_MENU_RAIDLEVEL: 622 case PMR_MENU_RAIDLEVEL:
623 process_menu(MENU_raidlevel, &retvalue); 623 process_menu(MENU_raidlevel, &retvalue);
624 if (retvalue >= 0) 624 if (retvalue >= 0)
625 dev_ptr->raid_level = retvalue; 625 dev_ptr->raid_level = retvalue;
626 return 0; 626 return 0;
627 case PMR_MENU_NUMROW: 627 case PMR_MENU_NUMROW:
628 hit_enter_to_continue(NULL, MSG_raid_nomultidim); 628 hit_enter_to_continue(NULL, MSG_raid_nomultidim);
629 return 0; 629 return 0;
630#if 0 /* notyet */ 630#if 0 /* notyet */
631 msg_to_show = MSG_raid_numrow_ask; 631 msg_to_show = MSG_raid_numrow_ask;
632 out_var = &(dev_ptr->numRow); 632 out_var = &(dev_ptr->numRow);
633 break; 633 break;
634#endif 634#endif
635 case PMR_MENU_NUMCOL: 635 case PMR_MENU_NUMCOL:
636 msg_to_show = MSG_raid_numcol_ask; 636 msg_to_show = MSG_raid_numcol_ask;
637 out_var = &(dev_ptr->numCol); 637 out_var = &(dev_ptr->numCol);
638 break; 638 break;
639 case PMR_MENU_NUMSPARE: 639 case PMR_MENU_NUMSPARE:
640 msg_to_show = MSG_raid_numspare_ask; 640 msg_to_show = MSG_raid_numspare_ask;
641 out_var = &(dev_ptr->numSpare); 641 out_var = &(dev_ptr->numSpare);
642 break; 642 break;
643 case PMR_MENU_SECTPERSU: 643 case PMR_MENU_SECTPERSU:
644 msg_to_show = MSG_raid_sectpersu_ask; 644 msg_to_show = MSG_raid_sectpersu_ask;
645 out_var = &(dev_ptr->sectPerSU); 645 out_var = &(dev_ptr->sectPerSU);
646 break; 646 break;
647 case PMR_MENU_SUSPERPARITYUNIT: 647 case PMR_MENU_SUSPERPARITYUNIT:
648 msg_to_show = MSG_raid_superpar_ask; 648 msg_to_show = MSG_raid_superpar_ask;
649 out_var = &(dev_ptr->SUsPerParityUnit); 649 out_var = &(dev_ptr->SUsPerParityUnit);
650 break; 650 break;
651 case PMR_MENU_SUSPERRECONUNIT: 651 case PMR_MENU_SUSPERRECONUNIT:
652 msg_to_show = MSG_raid_superrec_ask; 652 msg_to_show = MSG_raid_superrec_ask;
653 out_var = &(dev_ptr->SUsPerReconUnit); 653 out_var = &(dev_ptr->SUsPerReconUnit);
654 break; 654 break;
655 case PMR_MENU_REMOVE: 655 case PMR_MENU_REMOVE:
656 dev_ptr->enabled = 0; 656 dev_ptr->enabled = 0;
657 return 0; 657 return 0;
658 } 658 }
659 if (out_var == NULL || msg_to_show == NULL) 659 if (out_var == NULL || msg_to_show == NULL)
660 return -1; 660 return -1;
661 snprintf(buf, SSTRSIZE, "%d", *out_var); 661 snprintf(buf, SSTRSIZE, "%d", *out_var);
662 msg_prompt_win(msg_to_show, -1, 18, 0, 0, buf, buf, SSTRSIZE); 662 msg_prompt_win(msg_to_show, -1, 18, 0, 0, buf, buf, SSTRSIZE);
663 if (atoi(buf) >= 0) 663 if (atoi(buf) >= 0)
664 *out_var = atoi(buf); 664 *out_var = atoi(buf);
665 return 0; 665 return 0;
666} 666}
667 667
668static void 668static void
669pm_raid_init(void *arg, void *none) 669pm_raid_init(void *arg, void *none)
670{ 670{
671 struct raid_desc *dev_ptr = arg; 671 struct raid_desc *dev_ptr = arg;
672 memset(dev_ptr, 0, sizeof(*dev_ptr)); 672 memset(dev_ptr, 0, sizeof(*dev_ptr));
673 *dev_ptr = (struct raid_desc) { 673 *dev_ptr = (struct raid_desc) {
674 .enabled = 1, 674 .enabled = 1,
675 .blocked = 0, 675 .blocked = 0,
676 .sectPerSU = 32, 676 .sectPerSU = 32,
677 .SUsPerParityUnit = 1, 677 .SUsPerParityUnit = 1,
678 .SUsPerReconUnit = 1, 678 .SUsPerReconUnit = 1,
679 }; 679 };
680} 680}
681 681
682static int 682static int
683pm_raid_check(void *arg) 683pm_raid_check(void *arg)
684{ 684{
685 size_t i, dev_num = 0; 685 size_t i, dev_num = 0;
686 daddr_t min_size = 0, cur_size = 0; 686 daddr_t min_size = 0, cur_size = 0;
687 struct raid_desc *dev_ptr = arg; 687 struct raid_desc *dev_ptr = arg;
688 struct disk_part_info info; 688 struct disk_part_info info;
689 struct disk_partitions *parts; 689 struct disk_partitions *parts;
690 690
691 if (dev_ptr->blocked) 691 if (dev_ptr->blocked)
692 return 0; 692 return 0;
693 693
694 for (i = 0; i < MAX_IN_RAID; i++) { 694 for (i = 0; i < MAX_IN_RAID; i++) {
695 if (dev_ptr->comp[i].parts != NULL) { 695 if (dev_ptr->comp[i].parts != NULL) {
696 parts = dev_ptr->comp[i].parts; 696 parts = dev_ptr->comp[i].parts;
697 if (!parts->pscheme->get_part_info(parts, 697 if (!parts->pscheme->get_part_info(parts,
698 dev_ptr->comp[i].id, &info)) 698 dev_ptr->comp[i].id, &info))
699 continue; 699 continue;
700 cur_size = info.size; 700 cur_size = info.size;
701 if (cur_size < min_size || dev_num == 0) 701 if (cur_size < min_size || dev_num == 0)
702 min_size = cur_size; 702 min_size = cur_size;
703 if (dev_ptr->comp[i].is_spare) 703 if (dev_ptr->comp[i].is_spare)
704 continue; 704 continue;
705 dev_num++; 705 dev_num++;
706 } 706 }
707 } 707 }
708 708
709 /* Calculate sum of available space */ 709 /* Calculate sum of available space */
710 if (dev_num > 0) { 710 if (dev_num > 0) {
711 switch (dev_ptr->raid_level) { 711 switch (dev_ptr->raid_level) {
712 case 0: 712 case 0:
713 dev_ptr->total_size = min_size * dev_num; 713 dev_ptr->total_size = min_size * dev_num;
714 break; 714 break;
715 case 1: 715 case 1:
716 dev_ptr->total_size = min_size; 716 dev_ptr->total_size = min_size;
717 break; 717 break;
718 case 4: 718 case 4:
719 case 5: 719 case 5:
720 dev_ptr->total_size = min_size * (dev_num - 1); 720 dev_ptr->total_size = min_size * (dev_num - 1);
721 break; 721 break;
722 } 722 }
723 pm_manage_getfreenode(&(dev_ptr->node), "raid", &raids_t_info); 723 pm_manage_getfreenode(&(dev_ptr->node), "raid", &raids_t_info);
724 if (dev_ptr->node < 0) 724 if (dev_ptr->node < 0)
725 dev_ptr->enabled = 0; 725 dev_ptr->enabled = 0;
726 } 726 }
727 else 727 else
728 dev_ptr->enabled = 0; 728 dev_ptr->enabled = 0;
729 return dev_ptr->enabled; 729 return dev_ptr->enabled;
730} 730}
731 731
732static int 732static int
733pm_raid_disk_add(menudesc *m, void *arg) 733pm_raid_disk_add(menudesc *m, void *arg)
734{ 734{
735 int i; 735 int i;
736 struct raid_desc *dev_ptr = arg; 736 struct raid_desc *dev_ptr = arg;
737 struct part_entry disk_entrie = pm_dev_list(PM_RAID); 737 struct part_entry disk_entrie = pm_dev_list(PM_RAID);
738 if (pm_retvalue < 0) 738 if (pm_retvalue < 0)
739 return pm_retvalue; 739 return pm_retvalue;
740 740
741 for (i = 0; i < MAX_IN_RAID; i++) 741 for (i = 0; i < MAX_IN_RAID; i++)
742 if (dev_ptr->comp[i].parts == NULL) { 742 if (dev_ptr->comp[i].parts == NULL) {
743 dev_ptr->comp[i].parts = disk_entrie.parts; 743 dev_ptr->comp[i].parts = disk_entrie.parts;
744 dev_ptr->comp[i].id = disk_entrie.id; 744 dev_ptr->comp[i].id = disk_entrie.id;
745 dev_ptr->comp[i].is_spare = pm_raid_curspare; 745 dev_ptr->comp[i].is_spare = pm_raid_curspare;
746 strlcpy(dev_ptr->comp[i].name, disk_entrie.fullname, 746 strlcpy(dev_ptr->comp[i].name, disk_entrie.fullname,
747 sizeof dev_ptr->comp[i].name); 747 sizeof dev_ptr->comp[i].name);
748 if (pm_raid_curspare) 748 if (pm_raid_curspare)
749 dev_ptr->numSpare++; 749 dev_ptr->numSpare++;
750 else 750 else
751 dev_ptr->numCol++; 751 dev_ptr->numCol++;
752 dev_ptr->numRow = 1; 752 dev_ptr->numRow = 1;
753 break; 753 break;
754 } 754 }
755 return 0; 755 return 0;
756} 756}
757 757
758static int 758static int
759pm_raid_disk_del(menudesc *m, void *arg) 759pm_raid_disk_del(menudesc *m, void *arg)
760{ 760{
761 int retvalue = -1, num_devs = 0; 761 int retvalue = -1, num_devs = 0;
762 int i, pm_cur; 762 int i, pm_cur;
763 int menu_no; 763 int menu_no;
764 struct raid_desc *dev_ptr = arg; 764 struct raid_desc *dev_ptr = arg;
765 menu_ent menu_entries[MAX_IN_RAID]; 765 menu_ent menu_entries[MAX_IN_RAID];
766 struct part_entry submenu_args[MAX_IN_RAID]; 766 struct part_entry submenu_args[MAX_IN_RAID];
767 767
768 for (i = 0; i < MAX_IN_RAID; i++) { 768 for (i = 0; i < MAX_IN_RAID; i++) {
769 if (dev_ptr->comp[i].parts == NULL || 769 if (dev_ptr->comp[i].parts == NULL ||
770 dev_ptr->comp[i].is_spare != pm_raid_curspare) 770 dev_ptr->comp[i].is_spare != pm_raid_curspare)
771 continue; 771 continue;
772 menu_entries[num_devs] = (struct menu_ent) { 772 menu_entries[num_devs] = (struct menu_ent) {
773 .opt_name = dev_ptr->comp[i].name, 773 .opt_name = dev_ptr->comp[i].name,
774 .opt_action = set_menu_select, 774 .opt_action = set_menu_select,
775 .opt_flags = OPT_EXIT, 775 .opt_flags = OPT_EXIT,
776 }; 776 };
777 submenu_args[num_devs].dev_ptr = dev_ptr; 777 submenu_args[num_devs].dev_ptr = dev_ptr;
778 submenu_args[num_devs].index = i; 778 submenu_args[num_devs].index = i;
779 num_devs++; 779 num_devs++;
780 } 780 }
781 781
782 menu_no = new_menu(MSG_raid_disks, 782 menu_no = new_menu(MSG_raid_disks,
783 menu_entries, num_devs, -1, -1, 783 menu_entries, num_devs, -1, -1,
784 (num_devs+1<3)?3:num_devs+1, 13, 784 (num_devs+1<3)?3:num_devs+1, 13,
785 MC_SCROLL | MC_NOCLEAR, NULL, NULL, NULL, NULL, MSG_cancel); 785 MC_SCROLL | MC_NOCLEAR, NULL, NULL, NULL, NULL, MSG_cancel);
786 if (menu_no == -1) 786 if (menu_no == -1)
787 return -1; 787 return -1;
788 process_menu(menu_no, &retvalue); 788 process_menu(menu_no, &retvalue);
789 free_menu(menu_no); 789 free_menu(menu_no);
790 790
791 if (retvalue < 0 || retvalue >= num_devs) 791 if (retvalue < 0 || retvalue >= num_devs)
792 return -1; 792 return -1;
793 793
794 pm_cur = submenu_args[retvalue].index; 794 pm_cur = submenu_args[retvalue].index;
795 795
796 if (dev_ptr->comp[pm_cur].is_spare) 796 if (dev_ptr->comp[pm_cur].is_spare)
797 dev_ptr->numSpare--; 797 dev_ptr->numSpare--;
798 else 798 else
799 dev_ptr->numCol--; 799 dev_ptr->numCol--;
800 dev_ptr->numRow = (dev_ptr->numCol)?1:0; 800 dev_ptr->numRow = (dev_ptr->numCol)?1:0;
801 dev_ptr->comp[pm_cur].parts = NULL; 801 dev_ptr->comp[pm_cur].parts = NULL;
802 802
803 return 0; 803 return 0;
804} 804}
805 805
806static int 806static int
807pm_raid_commit(void) 807pm_raid_commit(void)
808{ 808{
809 int i, ii; 809 int i, ii;
810 FILE *f; 810 FILE *f;
811 char f_name[STRSIZE], devname[STRSIZE]; 811 char f_name[STRSIZE], devname[STRSIZE];
812 812
813 for (i = 0; i < MAX_RAID; i++) { 813 for (i = 0; i < MAX_RAID; i++) {
814 if (! pm_raid_check(&raids[i])) 814 if (! pm_raid_check(&raids[i]))
815 continue; 815 continue;
816 816
817 /* Generating configure file for our raid */ 817 /* Generating configure file for our raid */
818 snprintf(f_name, SSTRSIZE, "/tmp/raid.%d.conf", raids[i].node); 818 snprintf(f_name, SSTRSIZE, "/tmp/raid.%d.conf", raids[i].node);
819 f = fopen(f_name, "w"); 819 f = fopen(f_name, "w");
820 if (f == NULL) { 820 if (f == NULL) {
821 endwin(); 821 endwin();
822 (void)fprintf(stderr, 822 (void)fprintf(stderr,
823 "Could not open %s for writing\n", f_name); 823 "Could not open %s for writing\n", f_name);
824 if (logfp) 824 if (logfp)
825 (void)fprintf(logfp, 825 (void)fprintf(logfp,
826 "Could not open %s for writing\n", f_name); 826 "Could not open %s for writing\n", f_name);
827 return 1; 827 return 1;
828 } 828 }
829 scripting_fprintf(NULL, "cat <<EOF >%s\n", f_name); 829 scripting_fprintf(NULL, "cat <<EOF >%s\n", f_name);
830 scripting_fprintf(f, "START array\n%d %d %d\n", 830 scripting_fprintf(f, "START array\n%d %d %d\n",
831 raids[i].numRow, raids[i].numCol, raids[i].numSpare); 831 raids[i].numRow, raids[i].numCol, raids[i].numSpare);
832 832
833 scripting_fprintf(f, "\nSTART disks\n"); 833 scripting_fprintf(f, "\nSTART disks\n");
834 for (ii = 0; ii < MAX_IN_RAID; ii++) { 834 for (ii = 0; ii < MAX_IN_RAID; ii++) {
835 if (raids[i].comp[ii].parts != NULL && 835 if (raids[i].comp[ii].parts != NULL &&
836 !raids[i].comp[ii].is_spare) { 836 !raids[i].comp[ii].is_spare) {
837 strcpy(devname, raids[i].comp[ii].name); 837 strcpy(devname, raids[i].comp[ii].name);
838 if (raids[i].comp[ii].parts != NULL && 838 if (raids[i].comp[ii].parts != NULL &&
839 raids[i].comp[ii].id != NO_PART) { 839 raids[i].comp[ii].id != NO_PART) {
840 /* wedge may have moved */ 840 /* wedge may have moved */
841 raids[i].comp[ii].parts->pscheme-> 841 raids[i].comp[ii].parts->pscheme->
842 get_part_device( 842 get_part_device(
843 raids[i].comp[ii].parts, 843 raids[i].comp[ii].parts,
844 raids[i].comp[ii].id, 844 raids[i].comp[ii].id,
845 devname, sizeof devname, NULL, 845 devname, sizeof devname, NULL,
846 logical_name, true, true); 846 logical_name, true, true);
847 raids[i].comp[ii].parts->pscheme-> 847 raids[i].comp[ii].parts->pscheme->
848 get_part_device( 848 get_part_device(
849 raids[i].comp[ii].parts, 849 raids[i].comp[ii].parts,
850 raids[i].comp[ii].id, 850 raids[i].comp[ii].id,
851 raids[i].comp[ii].name, 851 raids[i].comp[ii].name,
852 sizeof raids[i].comp[ii].name, 852 sizeof raids[i].comp[ii].name,
853 NULL, plain_name, true, true); 853 NULL, plain_name, true, true);
854 } 854 }
855 scripting_fprintf(f, "%s\n", devname); 855 scripting_fprintf(f, "%s\n", devname);
856 } 856 }
857 } 857 }
858 858
859 scripting_fprintf(f, "\nSTART spare\n"); 859 scripting_fprintf(f, "\nSTART spare\n");
860 for (ii = 0; ii < MAX_IN_RAID; ii++) { 860 for (ii = 0; ii < MAX_IN_RAID; ii++) {
861 if (raids[i].comp[ii].parts != NULL && 861 if (raids[i].comp[ii].parts != NULL &&
862 raids[i].comp[ii].is_spare) { 862 raids[i].comp[ii].is_spare) {
863 strcpy(devname, raids[i].comp[ii].name); 863 strcpy(devname, raids[i].comp[ii].name);
864 if (raids[i].comp[ii].parts != NULL && 864 if (raids[i].comp[ii].parts != NULL &&
865 raids[i].comp[ii].id != NO_PART) { 865 raids[i].comp[ii].id != NO_PART) {
866 /* wedge may have moved */ 866 /* wedge may have moved */
867 raids[i].comp[ii].parts->pscheme-> 867 raids[i].comp[ii].parts->pscheme->
868 get_part_device( 868 get_part_device(
869 raids[i].comp[ii].parts, 869 raids[i].comp[ii].parts,
870 raids[i].comp[ii].id, 870 raids[i].comp[ii].id,
871 devname, sizeof devname, NULL, 871 devname, sizeof devname, NULL,
872 logical_name, true, true); 872 logical_name, true, true);
873 raids[i].comp[ii].parts->pscheme-> 873 raids[i].comp[ii].parts->pscheme->
874 get_part_device( 874 get_part_device(
875 raids[i].comp[ii].parts, 875 raids[i].comp[ii].parts,
876 raids[i].comp[ii].id, 876 raids[i].comp[ii].id,
877 raids[i].comp[ii].name, 877 raids[i].comp[ii].name,
878 sizeof raids[i].comp[ii].name, 878 sizeof raids[i].comp[ii].name,
879 NULL, plain_name, true, true); 879 NULL, plain_name, true, true);
880 } 880 }
881 881
882 scripting_fprintf(f, "%s\n", 882 scripting_fprintf(f, "%s\n",
883 devname); 883 devname);
884 } 884 }
885 } 885 }
886 886
887 scripting_fprintf(f, "\nSTART layout\n%d %d %d %d\n", 887 scripting_fprintf(f, "\nSTART layout\n%d %d %d %d\n",
888 raids[i].sectPerSU, raids[i].SUsPerParityUnit, 888 raids[i].sectPerSU, raids[i].SUsPerParityUnit,
889 raids[i].SUsPerReconUnit, raids[i].raid_level); 889 raids[i].SUsPerReconUnit, raids[i].raid_level);
890 890
891 scripting_fprintf(f, "\nSTART queue\nfifo 100\n\n"); 891 scripting_fprintf(f, "\nSTART queue\nfifo 100\n\n");
892 scripting_fprintf(NULL, "EOF\n"); 892 scripting_fprintf(NULL, "EOF\n");
893 fclose (f); 893 fclose (f);
894 fflush(NULL); 894 fflush(NULL);
895 895
896 /* Raid initialization */ 896 /* Raid initialization */
897 if (run_program(RUN_DISPLAY | RUN_PROGRESS, 897 if (run_program(RUN_DISPLAY | RUN_PROGRESS,
898 "raidctl -C %s raid%d", f_name, raids[i].node) == 0 && 898 "raidctl -C %s raid%d", f_name, raids[i].node) == 0 &&
899 run_program(RUN_DISPLAY | RUN_PROGRESS, 899 run_program(RUN_DISPLAY | RUN_PROGRESS,
900 "raidctl -I %d raid%d", rand(), raids[i].node) == 0 && 900 "raidctl -I %d raid%d", rand(), raids[i].node) == 0 &&
901 run_program(RUN_DISPLAY | RUN_PROGRESS, 901 run_program(RUN_DISPLAY | RUN_PROGRESS,
902 "raidctl -vi raid%d", raids[i].node) == 0 && 902 "raidctl -vi raid%d", raids[i].node) == 0 &&
903 run_program(RUN_DISPLAY | RUN_PROGRESS, 903 run_program(RUN_DISPLAY | RUN_PROGRESS,
904 "raidctl -v -A yes raid%d", raids[i].node) == 0) { 904 "raidctl -v -A yes raid%d", raids[i].node) == 0) {
905 /* 905 /*
906 * RAID creation done, remove it from list to 906 * RAID creation done, remove it from list to
907 * prevent its repeated reinitialization 907 * prevent its repeated reinitialization
908 */ 908 */
909 raids[i].blocked = 1; 909 raids[i].blocked = 1;
910 } 910 }
911 } 911 }
912 return 0; 912 return 0;
913} 913}
914 914
915/*** 915/***
916 VND 916 VND
917 ***/ 917 ***/
918 918
919static void 919static void
920pm_vnd_menufmt(menudesc *m, int opt, void *arg) 920pm_vnd_menufmt(menudesc *m, int opt, void *arg)
921{ 921{
922 struct vnd_desc *dev_ptr = ((struct part_entry *)arg)[opt].dev_ptr; 922 struct vnd_desc *dev_ptr = ((struct part_entry *)arg)[opt].dev_ptr;
923 char dev[STRSIZE]; 923 char dev[STRSIZE];
924 924
925 if (dev_ptr->enabled == 0) 925 if (dev_ptr->enabled == 0)
926 return; 926 return;
927 sprintf(dev, "vnd%d", dev_ptr->node); 927 sprintf(dev, "vnd%d", dev_ptr->node);
928 if (strlen(dev_ptr->filepath) < 1) 928 if (strlen(dev_ptr->filepath) < 1)
929 pm_fmt_disk_line(m->mw, dev, NULL, 929 pm_fmt_disk_line(m->mw, dev, NULL,
930 0, msg_string(MSG_vnd_err_menufmt)); 930 0, msg_string(MSG_vnd_err_menufmt));
931 else if (dev_ptr->is_exist) 931 else if (dev_ptr->is_exist)
932 pm_fmt_disk_line(m->mw, dev, dev_ptr->filepath, 932 pm_fmt_disk_line(m->mw, dev, dev_ptr->filepath,
933 0, msg_string(MSG_vnd_assign)); 933 0, msg_string(MSG_vnd_assign));
934 else 934 else
935 pm_fmt_disk_line(m->mw, dev, dev_ptr->filepath, 935 pm_fmt_disk_line(m->mw, dev, dev_ptr->filepath,
936 dev_ptr->size, NULL); 936 dev_ptr->size, NULL);
937} 937}
938 938
939static int 939static int
940max_msg_length(const msg *p, size_t cnt) 940max_msg_length(const msg *p, size_t cnt)
941{ 941{
942 int len, m = 0; 942 int len, m = 0;
943 943
944 while (cnt > 0) { 944 while (cnt > 0) {
945 len = strlen(msg_string(*p)); 945 len = strlen(msg_string(*p));
946 if (len > m) 946 if (len > m)
947 m = len; 947 m = len;
948 cnt--; p++; 948 cnt--; p++;
949 } 949 }
950 950
951 return m; 951 return m;
952} 952}
953 953
954static void 954static void
955pm_vnd_edit_menufmt(menudesc *m, int opt, void *arg) 955pm_vnd_edit_menufmt(menudesc *m, int opt, void *arg)
956{ 956{
957 struct vnd_desc *dev_ptr = arg; 957 struct vnd_desc *dev_ptr = arg;
958 char buf[SSTRSIZE]; 958 char buf[SSTRSIZE];
959 strcpy(buf, "-"); 959 strcpy(buf, "-");
960 static int lcol_width; 960 static int lcol_width;
961 if (lcol_width == 0) { 961 if (lcol_width == 0) {
962 static const msg labels[] = { 962 static const msg labels[] = {
963 MSG_vnd_path_fmt, MSG_vnd_assign_fmt, MSG_vnd_size_fmt, 963 MSG_vnd_path_fmt, MSG_vnd_assign_fmt, MSG_vnd_size_fmt,
964 MSG_vnd_ro_fmt, MSG_vnd_geom_fmt, MSG_vnd_bps_fmt, 964 MSG_vnd_ro_fmt, MSG_vnd_geom_fmt, MSG_vnd_bps_fmt,
965 MSG_vnd_spt_fmt, MSG_vnd_tpc_fmt, MSG_vnd_cyl_fmt 965 MSG_vnd_spt_fmt, MSG_vnd_tpc_fmt, MSG_vnd_cyl_fmt
966 }; 966 };
967 lcol_width = max_msg_length(labels, __arraycount(labels)) + 3; 967 lcol_width = max_msg_length(labels, __arraycount(labels)) + 3;
968 } 968 }
969 969
970 switch (opt) { 970 switch (opt) {
971 case PMV_MENU_FILEPATH: 971 case PMV_MENU_FILEPATH:
972 wprintw(m->mw, "%*s %s", -lcol_width, 972 wprintw(m->mw, "%*s %s", -lcol_width,
973 msg_string(MSG_vnd_path_fmt), dev_ptr->filepath); 973 msg_string(MSG_vnd_path_fmt), dev_ptr->filepath);
974 break; 974 break;
975 case PMV_MENU_EXIST: 975 case PMV_MENU_EXIST:
976 wprintw(m->mw, "%*s %s", -lcol_width, 976 wprintw(m->mw, "%*s %s", -lcol_width,
977 msg_string(MSG_vnd_assign_fmt), 977 msg_string(MSG_vnd_assign_fmt),
978 dev_ptr->is_exist? 978 dev_ptr->is_exist?
979 msg_string(MSG_No) : msg_string(MSG_Yes)); 979 msg_string(MSG_No) : msg_string(MSG_Yes));
980 break; 980 break;
981 case PMV_MENU_SIZE: 981 case PMV_MENU_SIZE:
982 if (!dev_ptr->is_exist) 982 if (!dev_ptr->is_exist)
983 snprintf(buf, SSTRSIZE, "%" PRIu64, 983 snprintf(buf, SSTRSIZE, "%" PRIu64,
984 dev_ptr->size / sizemult); 984 dev_ptr->size / sizemult);
985 wprintw(m->mw, "%*s %s", -lcol_width, 985 wprintw(m->mw, "%*s %s", -lcol_width,
986 msg_string(MSG_vnd_size_fmt), buf); 986 msg_string(MSG_vnd_size_fmt), buf);
987 break; 987 break;
988 case PMV_MENU_RO: 988 case PMV_MENU_RO:
989 wprintw(m->mw, "%*s %s", -lcol_width, 989 wprintw(m->mw, "%*s %s", -lcol_width,
990 msg_string(MSG_vnd_ro_fmt), 990 msg_string(MSG_vnd_ro_fmt),
991 dev_ptr->readonly? 991 dev_ptr->readonly?
992 msg_string(MSG_Yes) : msg_string(MSG_No)); 992 msg_string(MSG_Yes) : msg_string(MSG_No));
993 break; 993 break;
994 case PMV_MENU_MGEOM: 994 case PMV_MENU_MGEOM:
995 if (!dev_ptr->is_exist) 995 if (!dev_ptr->is_exist)
996 snprintf(buf, SSTRSIZE, "%s", 996 snprintf(buf, SSTRSIZE, "%s",
997 dev_ptr->manual_geom? 997 dev_ptr->manual_geom?
998 msg_string(MSG_Yes) : msg_string(MSG_No)); 998 msg_string(MSG_Yes) : msg_string(MSG_No));
999 wprintw(m->mw, "%*s %s", -lcol_width, 999 wprintw(m->mw, "%*s %s", -lcol_width,
1000 msg_string(MSG_vnd_geom_fmt), buf); 1000 msg_string(MSG_vnd_geom_fmt), buf);
@@ -1851,1563 +1851,1563 @@ pm_lvmlv_edit_menufmt(menudesc *m, int o @@ -1851,1563 +1851,1563 @@ pm_lvmlv_edit_menufmt(menudesc *m, int o
1851 snprintf(buf, STRSIZE, "%d", dev_ptr->stripes); 1851 snprintf(buf, STRSIZE, "%d", dev_ptr->stripes);
1852 wprintw(m->mw, "%-20s: %s", 1852 wprintw(m->mw, "%-20s: %s",
1853 msg_string(MSG_lvmlv_stripes_fmt), buf); 1853 msg_string(MSG_lvmlv_stripes_fmt), buf);
1854 break; 1854 break;
1855 case PMLV_MENU_STRIPESIZE: 1855 case PMLV_MENU_STRIPESIZE:
1856 if (dev_ptr->stripesize > 0) 1856 if (dev_ptr->stripesize > 0)
1857 snprintf(buf, STRSIZE, "%dK", dev_ptr->stripesize); 1857 snprintf(buf, STRSIZE, "%dK", dev_ptr->stripesize);
1858 wprintw(m->mw, "%-20s: %s", 1858 wprintw(m->mw, "%-20s: %s",
1859 msg_string(MSG_lvmlv_stripesiz_fmt), buf); 1859 msg_string(MSG_lvmlv_stripesiz_fmt), buf);
1860 break; 1860 break;
1861 case PMLV_MENU_ZERO: 1861 case PMLV_MENU_ZERO:
1862 wprintw(m->mw, "%-20s: %s", 1862 wprintw(m->mw, "%-20s: %s",
1863 msg_string(MSG_lvmlv_zero_fmt), 1863 msg_string(MSG_lvmlv_zero_fmt),
1864 dev_ptr->zero ? 1864 dev_ptr->zero ?
1865 msg_string(MSG_Yes) : msg_string(MSG_No)); 1865 msg_string(MSG_Yes) : msg_string(MSG_No));
1866 break; 1866 break;
1867 } 1867 }
1868} 1868}
1869 1869
1870static int 1870static int
1871pm_lvmlv_set_value(menudesc *m, void *arg) 1871pm_lvmlv_set_value(menudesc *m, void *arg)
1872{ 1872{
1873 char buf[STRSIZE]; 1873 char buf[STRSIZE];
1874 const char *msg_to_show = NULL; 1874 const char *msg_to_show = NULL;
1875 int *out_var = NULL; 1875 int *out_var = NULL;
1876 lv_t *dev_ptr = arg; 1876 lv_t *dev_ptr = arg;
1877 1877
1878 switch (m->cursel) { 1878 switch (m->cursel) {
1879 case PMLV_MENU_NAME: 1879 case PMLV_MENU_NAME:
1880 msg_prompt_win(MSG_lvmlv_name_ask, -1, 18, 0, 0, 1880 msg_prompt_win(MSG_lvmlv_name_ask, -1, 18, 0, 0,
1881 dev_ptr->name, dev_ptr->name, SSTRSIZE); 1881 dev_ptr->name, dev_ptr->name, SSTRSIZE);
1882 return 0; 1882 return 0;
1883 case PMLV_MENU_SIZE: 1883 case PMLV_MENU_SIZE:
1884 pm_edit_size_value(MSG_lvmlv_size_ask, 1884 pm_edit_size_value(MSG_lvmlv_size_ask,
1885 pm->sectorsize, pm->dlcylsize, 1885 pm->sectorsize, pm->dlcylsize,
1886 &dev_ptr->size); /* XXX cylsize? */ 1886 &dev_ptr->size); /* XXX cylsize? */
1887 break; 1887 break;
1888 case PMLV_MENU_READONLY: 1888 case PMLV_MENU_READONLY:
1889 dev_ptr->readonly = !dev_ptr->readonly; 1889 dev_ptr->readonly = !dev_ptr->readonly;
1890 return 0; 1890 return 0;
1891 case PMLV_MENU_CONTIGUOUS: 1891 case PMLV_MENU_CONTIGUOUS:
1892 dev_ptr->contiguous = !dev_ptr->contiguous; 1892 dev_ptr->contiguous = !dev_ptr->contiguous;
1893 return 0; 1893 return 0;
1894 case PMLV_MENU_EXTENTS: 1894 case PMLV_MENU_EXTENTS:
1895 msg_prompt_win(MSG_lvmlv_extnum_ask, -1, 18, 0, 0, 1895 msg_prompt_win(MSG_lvmlv_extnum_ask, -1, 18, 0, 0,
1896 dev_ptr->extents, dev_ptr->extents, SSTRSIZE); 1896 dev_ptr->extents, dev_ptr->extents, SSTRSIZE);
1897 return 0; 1897 return 0;
1898 case PMLV_MENU_MINOR: 1898 case PMLV_MENU_MINOR:
1899 msg_to_show = MSG_lvmlv_minor_ask; 1899 msg_to_show = MSG_lvmlv_minor_ask;
1900 out_var = &(dev_ptr->minor); 1900 out_var = &(dev_ptr->minor);
1901 break; 1901 break;
1902 case PMLV_MENU_MIRRORS: 1902 case PMLV_MENU_MIRRORS:
1903 msg_to_show = MSG_lvmlv_mirrors_ask; 1903 msg_to_show = MSG_lvmlv_mirrors_ask;
1904 out_var = &(dev_ptr->mirrors); 1904 out_var = &(dev_ptr->mirrors);
1905 break; 1905 break;
1906 case PMLV_MENU_REGIONSIZE: 1906 case PMLV_MENU_REGIONSIZE:
1907 msg_to_show = MSG_lvmlv_regsiz_ask; 1907 msg_to_show = MSG_lvmlv_regsiz_ask;
1908 out_var = &(dev_ptr->regionsize); 1908 out_var = &(dev_ptr->regionsize);
1909 break; 1909 break;
1910 case PMLV_MENU_PERSISTENT: 1910 case PMLV_MENU_PERSISTENT:
1911 dev_ptr->persistent = !dev_ptr->persistent; 1911 dev_ptr->persistent = !dev_ptr->persistent;
1912 return 0; 1912 return 0;
1913 case PMLV_MENU_READAHEAD: 1913 case PMLV_MENU_READAHEAD:
1914 msg_to_show = MSG_lvmlv_readahsect_ask; 1914 msg_to_show = MSG_lvmlv_readahsect_ask;
1915 out_var = &(dev_ptr->readahead); 1915 out_var = &(dev_ptr->readahead);
1916 break; 1916 break;
1917 case PMLV_MENU_STRIPES: 1917 case PMLV_MENU_STRIPES:
1918 msg_to_show = MSG_lvmlv_stripes_ask; 1918 msg_to_show = MSG_lvmlv_stripes_ask;
1919 out_var = &(dev_ptr->stripes); 1919 out_var = &(dev_ptr->stripes);
1920 break; 1920 break;
1921 case PMLV_MENU_STRIPESIZE: 1921 case PMLV_MENU_STRIPESIZE:
1922 if (dev_ptr->stripesize << 1 > 512) 1922 if (dev_ptr->stripesize << 1 > 512)
1923 dev_ptr->stripesize = 4; 1923 dev_ptr->stripesize = 4;
1924 else 1924 else
1925 dev_ptr->stripesize <<= 1; 1925 dev_ptr->stripesize <<= 1;
1926 return 0; 1926 return 0;
1927 case PMLV_MENU_ZERO: 1927 case PMLV_MENU_ZERO:
1928 dev_ptr->zero = !dev_ptr->zero; 1928 dev_ptr->zero = !dev_ptr->zero;
1929 return 0; 1929 return 0;
1930 case PMLV_MENU_REMOVE: 1930 case PMLV_MENU_REMOVE:
1931 dev_ptr->size = 0; 1931 dev_ptr->size = 0;
1932 return 0; 1932 return 0;
1933 } 1933 }
1934 if (out_var == NULL || msg_to_show == NULL) 1934 if (out_var == NULL || msg_to_show == NULL)
1935 return -1; 1935 return -1;
1936 snprintf(buf, SSTRSIZE, "%d", *out_var); 1936 snprintf(buf, SSTRSIZE, "%d", *out_var);
1937 msg_prompt_win(msg_to_show, -1, 18, 0, 0, buf, buf, SSTRSIZE); 1937 msg_prompt_win(msg_to_show, -1, 18, 0, 0, buf, buf, SSTRSIZE);
1938 if (atoi(buf) >= 0) 1938 if (atoi(buf) >= 0)
1939 *out_var = atoi(buf); 1939 *out_var = atoi(buf);
1940 return 0; 1940 return 0;
1941} 1941}
1942 1942
1943static void 1943static void
1944pm_lvmlv_init(void *arg, void *none) 1944pm_lvmlv_init(void *arg, void *none)
1945{ 1945{
1946 lv_t *dev_ptr = arg; 1946 lv_t *dev_ptr = arg;
1947 memset(dev_ptr, 0, sizeof *(dev_ptr)); 1947 memset(dev_ptr, 0, sizeof *(dev_ptr));
1948 *dev_ptr = (struct lv_t) { 1948 *dev_ptr = (struct lv_t) {
1949 .blocked = 0, 1949 .blocked = 0,
1950 .size = 1024, 1950 .size = 1024,
1951 .stripesize = 64, 1951 .stripesize = 64,
1952 }; 1952 };
1953 sprintf (dev_ptr->name, "lvol%.2d", rand()%100); 1953 sprintf (dev_ptr->name, "lvol%.2d", rand()%100);
1954} 1954}
1955 1955
1956static int 1956static int
1957pm_lvmlv_check(void *arg) 1957pm_lvmlv_check(void *arg)
1958{ 1958{
1959 lv_t *dev_ptr = arg; 1959 lv_t *dev_ptr = arg;
1960 if (dev_ptr->size > 0 && strlen(dev_ptr->name) > 0) 1960 if (dev_ptr->size > 0 && strlen(dev_ptr->name) > 0)
1961 return 1; 1961 return 1;
1962 else { 1962 else {
1963 dev_ptr->size = 0; 1963 dev_ptr->size = 0;
1964 return 0; 1964 return 0;
1965 } 1965 }
1966} 1966}
1967 1967
1968static int 1968static int
1969pm_lvm_commit(void) 1969pm_lvm_commit(void)
1970{ 1970{
1971 int i, ii, error; 1971 int i, ii, error;
1972 uint used_size = 0; 1972 uint used_size = 0;
1973 char params[STRSIZE*3], devs[STRSIZE*3], arg[STRSIZE]; 1973 char params[STRSIZE*3], devs[STRSIZE*3], arg[STRSIZE];
1974 1974
1975 for (i = 0; i < MAX_LVM_VG; i++) { 1975 for (i = 0; i < MAX_LVM_VG; i++) {
1976 /* Stage 0: checks */ 1976 /* Stage 0: checks */
1977 if (! pm_lvm_check(&lvms[i])) 1977 if (! pm_lvm_check(&lvms[i]))
1978 continue; 1978 continue;
1979 for (ii = 0; ii < MAX_LVM_LV; ii++) 1979 for (ii = 0; ii < MAX_LVM_LV; ii++)
1980 used_size += lvms[i].lv[ii].size; 1980 used_size += lvms[i].lv[ii].size;
1981 if (used_size > lvms[i].total_size) 1981 if (used_size > lvms[i].total_size)
1982 continue; 1982 continue;
1983 1983
1984 params[0] = '\0'; 1984 params[0] = '\0';
1985 devs[0] = '\0'; 1985 devs[0] = '\0';
1986 error = 0; 1986 error = 0;
1987 /* Stage 1: creating Physical Volumes (PV's) */ 1987 /* Stage 1: creating Physical Volumes (PV's) */
1988 for (ii = 0; ii < MAX_LVM_PV && ! error; ii++) 1988 for (ii = 0; ii < MAX_LVM_PV && ! error; ii++)
1989 if (lvms[i].pv[ii].pm != NULL) { 1989 if (lvms[i].pv[ii].pm != NULL) {
1990 run_program(RUN_SILENT | RUN_ERROR_OK, 1990 run_program(RUN_SILENT | RUN_ERROR_OK,
1991 "lvm pvremove -ffy /dev/r%s", 1991 "lvm pvremove -ffy /dev/r%s",
1992 (char*)lvms[i].pv[ii].pm_name); 1992 (char*)lvms[i].pv[ii].pm_name);
1993 error += run_program(RUN_DISPLAY | RUN_PROGRESS, 1993 error += run_program(RUN_DISPLAY | RUN_PROGRESS,
1994 "lvm pvcreate -ffy /dev/r%s", 1994 "lvm pvcreate -ffy /dev/r%s",
1995 (char*)lvms[i].pv[ii].pm_name); 1995 (char*)lvms[i].pv[ii].pm_name);
1996 if (error) 1996 if (error)
1997 break; 1997 break;
1998 strlcat(devs, " /dev/r", sizeof devs); 1998 strlcat(devs, " /dev/r", sizeof devs);
1999 strlcat(devs, lvms[i].pv[ii].pm_name, 1999 strlcat(devs, lvms[i].pv[ii].pm_name,
2000 sizeof devs); 2000 sizeof devs);
2001 } 2001 }
2002 if (error) 2002 if (error)
2003 continue; 2003 continue;
2004 /* Stage 2: creating Volume Groups (VG's) */ 2004 /* Stage 2: creating Volume Groups (VG's) */
2005 if (lvms[i].maxlogicalvolumes > 0) { 2005 if (lvms[i].maxlogicalvolumes > 0) {
2006 snprintf(arg, sizeof arg, " -l %d", 2006 snprintf(arg, sizeof arg, " -l %d",
2007 lvms[i].maxlogicalvolumes); 2007 lvms[i].maxlogicalvolumes);
2008 strlcat(params, arg, sizeof params); 2008 strlcat(params, arg, sizeof params);
2009 } 2009 }
2010 if (lvms[i].maxphysicalvolumes > 0) { 2010 if (lvms[i].maxphysicalvolumes > 0) {
2011 snprintf(arg, sizeof arg, " -p %d", 2011 snprintf(arg, sizeof arg, " -p %d",
2012 lvms[i].maxphysicalvolumes); 2012 lvms[i].maxphysicalvolumes);
2013 strlcat(params, arg, sizeof params); 2013 strlcat(params, arg, sizeof params);
2014 } 2014 }
2015 if (lvms[i].physicalextentsize > 0) { 2015 if (lvms[i].physicalextentsize > 0) {
2016 snprintf(arg, sizeof arg, " -s %d", 2016 snprintf(arg, sizeof arg, " -s %d",
2017 lvms[i].physicalextentsize); 2017 lvms[i].physicalextentsize);
2018 strlcat(params, arg, sizeof params); 2018 strlcat(params, arg, sizeof params);
2019 } 2019 }
2020 error += run_program(RUN_DISPLAY | RUN_PROGRESS, 2020 error += run_program(RUN_DISPLAY | RUN_PROGRESS,
2021 "lvm vgcreate %s %s %s", params, lvms[i].name, devs); 2021 "lvm vgcreate %s %s %s", params, lvms[i].name, devs);
2022 if (error) 2022 if (error)
2023 continue; 2023 continue;
2024 /* Stage 3: creating Logical Volumes (LV's) */ 2024 /* Stage 3: creating Logical Volumes (LV's) */
2025 for (ii = 0; ii < MAX_LVM_LV; ii++) { 2025 for (ii = 0; ii < MAX_LVM_LV; ii++) {
2026 if (lvms[i].lv[ii].size <= 0) 2026 if (lvms[i].lv[ii].size <= 0)
2027 continue; 2027 continue;
2028 2028
2029 params[0] = '\0'; 2029 params[0] = '\0';
2030 snprintf(arg, sizeof arg, " -C %c", 2030 snprintf(arg, sizeof arg, " -C %c",
2031 lvms[i].lv[ii].contiguous?'y':'n'); 2031 lvms[i].lv[ii].contiguous?'y':'n');
2032 strlcat(params, arg, sizeof params); 2032 strlcat(params, arg, sizeof params);
2033 snprintf(arg, sizeof arg, " -M %c", 2033 snprintf(arg, sizeof arg, " -M %c",
2034 lvms[i].lv[ii].persistent?'y':'n'); 2034 lvms[i].lv[ii].persistent?'y':'n');
2035 strlcat(params, arg, sizeof params); 2035 strlcat(params, arg, sizeof params);
2036 snprintf(arg, sizeof arg, " -p %s", 2036 snprintf(arg, sizeof arg, " -p %s",
2037 lvms[i].lv[ii].readonly?"r":"rw"); 2037 lvms[i].lv[ii].readonly?"r":"rw");
2038 strlcat(params, arg, sizeof params); 2038 strlcat(params, arg, sizeof params);
2039 snprintf(arg, sizeof arg, " -Z %c", 2039 snprintf(arg, sizeof arg, " -Z %c",
2040 lvms[i].lv[ii].zero?'y':'n'); 2040 lvms[i].lv[ii].zero?'y':'n');
2041 strlcat(params, arg, sizeof params); 2041 strlcat(params, arg, sizeof params);
2042 if (strlen(lvms[i].lv[ii].name) > 0) { 2042 if (strlen(lvms[i].lv[ii].name) > 0) {
2043 snprintf(arg, sizeof arg, " -n %s", 2043 snprintf(arg, sizeof arg, " -n %s",
2044 lvms[i].lv[ii].name); 2044 lvms[i].lv[ii].name);
2045 strlcat(params, arg, sizeof params); 2045 strlcat(params, arg, sizeof params);
2046 } 2046 }
2047 if (strlen(lvms[i].lv[ii].extents) > 0) { 2047 if (strlen(lvms[i].lv[ii].extents) > 0) {
2048 snprintf(arg, sizeof arg, " -l %s", 2048 snprintf(arg, sizeof arg, " -l %s",
2049 lvms[i].lv[ii].extents); 2049 lvms[i].lv[ii].extents);
2050 strlcat(params, arg, sizeof params); 2050 strlcat(params, arg, sizeof params);
2051 } 2051 }
2052 if (lvms[i].lv[ii].minor > 0) { 2052 if (lvms[i].lv[ii].minor > 0) {
2053 snprintf(arg, sizeof arg, " --minor %d", 2053 snprintf(arg, sizeof arg, " --minor %d",
2054 lvms[i].lv[ii].minor); 2054 lvms[i].lv[ii].minor);
2055 strlcat(params, arg, sizeof params); 2055 strlcat(params, arg, sizeof params);
2056 } 2056 }
2057 if (lvms[i].lv[ii].mirrors > 0) { 2057 if (lvms[i].lv[ii].mirrors > 0) {
2058 snprintf(arg, sizeof arg, " -m %d", 2058 snprintf(arg, sizeof arg, " -m %d",
2059 lvms[i].lv[ii].mirrors); 2059 lvms[i].lv[ii].mirrors);
2060 strlcat(params, arg, sizeof params); 2060 strlcat(params, arg, sizeof params);
2061 if (lvms[i].lv[ii].regionsize > 0) { 2061 if (lvms[i].lv[ii].regionsize > 0) {
2062 snprintf(arg, sizeof arg, " -R %d", 2062 snprintf(arg, sizeof arg, " -R %d",
2063 lvms[i].lv[ii].regionsize); 2063 lvms[i].lv[ii].regionsize);
2064 strlcat(params, arg, sizeof params); 2064 strlcat(params, arg, sizeof params);
2065 } 2065 }
2066 } 2066 }
2067 if (lvms[i].lv[ii].readahead > 0) { 2067 if (lvms[i].lv[ii].readahead > 0) {
2068 snprintf(arg, sizeof arg, " -r %d", 2068 snprintf(arg, sizeof arg, " -r %d",
2069 lvms[i].lv[ii].readahead); 2069 lvms[i].lv[ii].readahead);
2070 strlcat(params, arg, sizeof params); 2070 strlcat(params, arg, sizeof params);
2071 } 2071 }
2072 if (lvms[i].lv[ii].stripes > 0) { 2072 if (lvms[i].lv[ii].stripes > 0) {
2073 snprintf(arg, sizeof arg, " -i %d", 2073 snprintf(arg, sizeof arg, " -i %d",
2074 lvms[i].lv[ii].stripes); 2074 lvms[i].lv[ii].stripes);
2075 strlcat(params, arg, sizeof params); 2075 strlcat(params, arg, sizeof params);
2076 if (lvms[i].lv[ii].stripesize > 0) { 2076 if (lvms[i].lv[ii].stripesize > 0) {
2077 snprintf(arg, sizeof arg, " -I %d", 2077 snprintf(arg, sizeof arg, " -I %d",
2078 lvms[i].lv[ii].stripesize); 2078 lvms[i].lv[ii].stripesize);
2079 strlcat(params, arg, sizeof params); 2079 strlcat(params, arg, sizeof params);
2080 } 2080 }
2081 } 2081 }
2082 snprintf(arg, sizeof arg, " -L %" PRIi64 "M", 2082 snprintf(arg, sizeof arg, " -L %" PRIi64 "M",
2083 lvms[i].lv[ii].size); 2083 lvms[i].lv[ii].size);
2084 strlcat(params, arg, sizeof params); 2084 strlcat(params, arg, sizeof params);
2085 2085
2086 error += run_program(RUN_DISPLAY | RUN_PROGRESS, 2086 error += run_program(RUN_DISPLAY | RUN_PROGRESS,
2087 "lvm lvcreate %s %s", params, lvms[i].name); 2087 "lvm lvcreate %s %s", params, lvms[i].name);
2088 } 2088 }
2089 if (! error) { 2089 if (! error) {
2090 lvms[i].blocked = 1; 2090 lvms[i].blocked = 1;
2091 for (ii = 0; ii < MAX_LVM_PV; ii++) 2091 for (ii = 0; ii < MAX_LVM_PV; ii++)
2092 if (lvms[i].pv[ii].pm != NULL) 2092 if (lvms[i].pv[ii].pm != NULL)
2093 lvms[i].pv[ii].pm->blocked++; 2093 lvms[i].pv[ii].pm->blocked++;
2094 for (ii = 0; ii < MAX_LVM_LV; ii++) 2094 for (ii = 0; ii < MAX_LVM_LV; ii++)
2095 if (lvms[i].lv[ii].size > 0) 2095 if (lvms[i].lv[ii].size > 0)
2096 lvms[i].lv[ii].blocked = 1; 2096 lvms[i].lv[ii].blocked = 1;
2097 } 2097 }
2098 } 2098 }
2099 2099
2100 return 0; 2100 return 0;
2101} 2101}
2102 2102
2103/*** 2103/***
2104 Partman generic functions 2104 Partman generic functions
2105 ***/ 2105 ***/
2106 2106
2107int 2107int
2108pm_getrefdev(struct pm_devs *pm_cur) 2108pm_getrefdev(struct pm_devs *pm_cur)
2109{ 2109{
2110 int i, ii, dev_num, num_devs, num_devs_s; 2110 int i, ii, dev_num, num_devs, num_devs_s;
2111 char descr[MENUSTRSIZE], dev[MENUSTRSIZE] = ""; 2111 char descr[MENUSTRSIZE], dev[MENUSTRSIZE] = "";
2112 2112
2113 pm_cur->refdev = NULL; 2113 pm_cur->refdev = NULL;
2114 if (! strncmp(pm_cur->diskdev, "cgd", 3)) { 2114 if (! strncmp(pm_cur->diskdev, "cgd", 3)) {
2115 dev_num = pm_cur->diskdev[3] - '0'; 2115 dev_num = pm_cur->diskdev[3] - '0';
2116 for (i = 0; i < MAX_CGD; i++) 2116 for (i = 0; i < MAX_CGD; i++)
2117 if (cgds[i].blocked && cgds[i].node == dev_num) { 2117 if (cgds[i].blocked && cgds[i].node == dev_num) {
2118 pm_cur->refdev = &cgds[i]; 2118 pm_cur->refdev = &cgds[i];
2119 snprintf(descr, sizeof descr, 2119 snprintf(descr, sizeof descr,
2120 " (%s, %s-%d)", cgds[i].pm_name, 2120 " (%s, %s-%d)", cgds[i].pm_name,
2121 cgds[i].enc_type, cgds[i].key_size); 2121 cgds[i].enc_type, cgds[i].key_size);
2122 strlcat(pm_cur->diskdev_descr, descr, 2122 strlcat(pm_cur->diskdev_descr, descr,
2123 sizeof(pm_cur->diskdev_descr)); 2123 sizeof(pm_cur->diskdev_descr));
2124 break; 2124 break;
2125 } 2125 }
2126 } else if (! strncmp(pm_cur->diskdev, "vnd", 3)) { 2126 } else if (! strncmp(pm_cur->diskdev, "vnd", 3)) {
2127 dev_num = pm_cur->diskdev[3] - '0'; 2127 dev_num = pm_cur->diskdev[3] - '0';
2128 for (i = 0; i < MAX_VND; i++) 2128 for (i = 0; i < MAX_VND; i++)
2129 if (vnds[i].blocked && vnds[i].node == dev_num) { 2129 if (vnds[i].blocked && vnds[i].node == dev_num) {
2130 pm_cur->refdev = &vnds[i]; 2130 pm_cur->refdev = &vnds[i];
2131 vnds[i].pm->parts->pscheme->get_part_device( 2131 vnds[i].pm->parts->pscheme->get_part_device(
2132 vnds[i].pm->parts, vnds[i].pm_part, 2132 vnds[i].pm->parts, vnds[i].pm_part,
2133 dev, sizeof dev, NULL, plain_name, false, 2133 dev, sizeof dev, NULL, plain_name, false,
2134 true); 2134 true);
2135 snprintf(descr, sizeof descr, " (%s, %s)", 2135 snprintf(descr, sizeof descr, " (%s, %s)",
2136 dev, vnds[i].filepath); 2136 dev, vnds[i].filepath);
2137 strlcat(pm_cur->diskdev_descr, descr, 2137 strlcat(pm_cur->diskdev_descr, descr,
2138 sizeof(pm_cur->diskdev_descr)); 2138 sizeof(pm_cur->diskdev_descr));
2139 break; 2139 break;
2140 } 2140 }
2141 } else if (! strncmp(pm_cur->diskdev, "raid", 4)) { 2141 } else if (! strncmp(pm_cur->diskdev, "raid", 4)) {
2142 dev_num = pm_cur->diskdev[4] - '0'; 2142 dev_num = pm_cur->diskdev[4] - '0';
2143 for (i = 0; i < MAX_RAID; i++) 2143 for (i = 0; i < MAX_RAID; i++)
2144 if (raids[i].blocked && raids[i].node == dev_num) { 2144 if (raids[i].blocked && raids[i].node == dev_num) {
2145 pm_cur->refdev = &raids[i]; 2145 pm_cur->refdev = &raids[i];
2146 num_devs = 0; num_devs_s = 0; 2146 num_devs = 0; num_devs_s = 0;
2147 for (ii = 0; ii < MAX_IN_RAID; ii++) 2147 for (ii = 0; ii < MAX_IN_RAID; ii++)
2148 if (raids[i].comp[ii].parts != NULL) { 2148 if (raids[i].comp[ii].parts != NULL) {
2149 if(raids[i].comp[ii].is_spare) 2149 if(raids[i].comp[ii].is_spare)
2150 num_devs_s++; 2150 num_devs_s++;
2151 else 2151 else
2152 num_devs++; 2152 num_devs++;
2153 } 2153 }
2154 snprintf(descr, sizeof descr, 2154 snprintf(descr, sizeof descr,
2155 " (lvl %d, %d disks, %d spare)", 2155 " (lvl %d, %d disks, %d spare)",
2156 raids[i].raid_level, num_devs, 2156 raids[i].raid_level, num_devs,
2157 num_devs_s); 2157 num_devs_s);
2158 strlcat(pm_cur->diskdev_descr, descr, 2158 strlcat(pm_cur->diskdev_descr, descr,
2159 sizeof(pm_cur->diskdev_descr)); 2159 sizeof(pm_cur->diskdev_descr));
2160 break; 2160 break;
2161 } 2161 }
2162 } else 2162 } else
2163 return -1; 2163 return -1;
2164 return 0; 2164 return 0;
2165} 2165}
2166 2166
2167/* 2167/*
2168 * Enable/disable items in the extended partition disk/partition action 2168 * Enable/disable items in the extended partition disk/partition action
2169 * menu 2169 * menu
2170 */ 2170 */
2171void 2171void
2172pmdiskentry_enable(menudesc *menu, struct part_entry *pe) 2172pmdiskentry_enable(menudesc *menu, struct part_entry *pe)
2173{ 2173{
2174 int i; 2174 int i;
2175 menu_ent *m; 2175 menu_ent *m;
2176 bool enable; 2176 bool enable;
2177 2177
2178 for (i = 0; i < menu->numopts; i++) { 2178 for (i = 0; i < menu->numopts; i++) {
2179 m = &menu->opts[i]; 2179 m = &menu->opts[i];
2180 2180
2181 enable = false; 2181 enable = false;
2182 if (m->opt_name == MSG_unconfig) { 2182 if (m->opt_name == MSG_unconfig) {
2183 if (pe->type == PM_DISK) 2183 if (pe->type == PM_DISK)
2184 enable = ((struct pm_devs *)pe->dev_ptr) 2184 enable = ((struct pm_devs *)pe->dev_ptr)
2185 ->refdev != NULL; 2185 ->refdev != NULL;
2186 } else if (m->opt_name == MSG_undo) { 2186 } else if (m->opt_name == MSG_undo) {
2187 if (pe->type != PM_DISK) 2187 if (pe->type != PM_DISK)
2188 continue; 2188 continue;
2189 enable = ((struct pm_devs *)pe->dev_ptr)->unsaved; 2189 enable = ((struct pm_devs *)pe->dev_ptr)->unsaved;
2190 } else if (m->opt_name == MSG_switch_parts) { 2190 } else if (m->opt_name == MSG_switch_parts) {
2191 enable = pm_from_pe(pe)->parts != NULL; 2191 enable = pm_from_pe(pe)->parts != NULL;
2192 } else { 2192 } else {
2193 continue; 2193 continue;
2194 } 2194 }
2195 2195
2196 if (enable) 2196 if (enable)
2197 m->opt_flags &= ~OPT_IGNORE; 2197 m->opt_flags &= ~OPT_IGNORE;
2198 else 2198 else
2199 m->opt_flags |= OPT_IGNORE; 2199 m->opt_flags |= OPT_IGNORE;
2200 } 2200 }
2201} 2201}
2202 2202
2203/* Detect that partition is in use */ 2203/* Detect that partition is in use */
2204int 2204int
2205pm_partusage(struct pm_devs *pm_cur, int part_num, int do_del) 2205pm_partusage(struct pm_devs *pm_cur, int part_num, int do_del)
2206{ 2206{
2207 int i, ii, retvalue = 0; 2207 int i, ii, retvalue = 0;
2208 struct disk_part_info info; 2208 struct disk_part_info info;
2209 part_id id; 2209 part_id id;
2210 2210
2211 if (pm_cur->parts == NULL) 2211 if (pm_cur->parts == NULL)
2212 return -1; /* nothing can be in use */ 2212 return -1; /* nothing can be in use */
2213 2213
2214 if (part_num < 0) { 2214 if (part_num < 0) {
2215 /* Check all partitions on device */ 2215 /* Check all partitions on device */
2216 for (id = 0; id < pm_cur->parts->num_part; id++) { 2216 for (id = 0; id < pm_cur->parts->num_part; id++) {
2217 if (!pm_cur->parts->pscheme->get_part_info( 2217 if (!pm_cur->parts->pscheme->get_part_info(
2218 pm_cur->parts, id, &info)) 2218 pm_cur->parts, id, &info))
2219 continue; 2219 continue;
2220 if (info.flags & (PTI_SEC_CONTAINER| 2220 if (info.flags & (PTI_SEC_CONTAINER|
2221 PTI_WHOLE_DISK|PTI_PSCHEME_INTERNAL| 2221 PTI_WHOLE_DISK|PTI_PSCHEME_INTERNAL|
2222 PTI_RAW_PART)) 2222 PTI_RAW_PART))
2223 continue; 2223 continue;
2224 retvalue += pm_partusage(pm_cur, id, do_del); 2224 retvalue += pm_partusage(pm_cur, id, do_del);
2225 } 2225 }
2226 return retvalue; 2226 return retvalue;
2227 } 2227 }
2228 2228
2229 id = (part_id)part_num; 2229 id = (part_id)part_num;
2230 if (id >= pm_cur->parts->num_part) 2230 if (id >= pm_cur->parts->num_part)
2231 return 0; 2231 return 0;
2232 2232
2233 for (i = 0; i < MAX_CGD; i++) 2233 for (i = 0; i < MAX_CGD; i++)
2234 if (cgds[i].enabled && 2234 if (cgds[i].enabled &&
2235 cgds[i].pm == pm_cur && 2235 cgds[i].pm == pm_cur &&
2236 cgds[i].pm_part == id) { 2236 cgds[i].pm_part == id) {
2237 if (do_del) { 2237 if (do_del) {
2238 cgds[i].pm = NULL; 2238 cgds[i].pm = NULL;
2239 cgds[i].pm_name[0] = '\0'; 2239 cgds[i].pm_name[0] = '\0';
2240 } 2240 }
2241 return 1; 2241 return 1;
2242 } 2242 }
2243 for (i = 0; i < MAX_RAID; i++) 2243 for (i = 0; i < MAX_RAID; i++)
2244 for (ii = 0; ii < MAX_IN_RAID; ii++) 2244 for (ii = 0; ii < MAX_IN_RAID; ii++)
2245 if (raids[i].enabled && 2245 if (raids[i].enabled &&
2246 raids[i].comp[ii].parts == pm_cur->parts && 2246 raids[i].comp[ii].parts == pm_cur->parts &&
2247 raids[i].comp[ii].id == id) { 2247 raids[i].comp[ii].id == id) {
2248 if (do_del) 2248 if (do_del)
2249 raids[i].comp[ii].parts = NULL; 2249 raids[i].comp[ii].parts = NULL;
2250 return 1; 2250 return 1;
2251 } 2251 }
2252 for (i = 0; i < MAX_LVM_VG; i++) 2252 for (i = 0; i < MAX_LVM_VG; i++)
2253 for (ii = 0; ii < MAX_LVM_PV; ii++) 2253 for (ii = 0; ii < MAX_LVM_PV; ii++)
2254 if (lvms[i].enabled && 2254 if (lvms[i].enabled &&
2255 lvms[i].pv[ii].pm == pm_cur && 2255 lvms[i].pv[ii].pm == pm_cur &&
2256 lvms[i].pv[ii].pm_part == id) { 2256 lvms[i].pv[ii].pm_part == id) {
2257 if (do_del) 2257 if (do_del)
2258 lvms[i].pv[ii].pm = NULL; 2258 lvms[i].pv[ii].pm = NULL;
2259 return 1; 2259 return 1;
2260 } 2260 }
2261 2261
2262 return 0; 2262 return 0;
2263} 2263}
2264 2264
2265static void 2265static void
2266pm_destroy_one(struct pm_devs *pm_i) 2266pm_destroy_one(struct pm_devs *pm_i)
2267{ 2267{
2268 part_id i; 2268 part_id i;
2269 2269
2270 if (pm_i->parts != NULL) { 2270 if (pm_i->parts != NULL) {
2271 if (pm_i->mounted != NULL) { 2271 if (pm_i->mounted != NULL) {
2272 for (i = 0; i < pm_i->parts->num_part; i++) 2272 for (i = 0; i < pm_i->parts->num_part; i++)
2273 free(pm_i->mounted[i]); 2273 free(pm_i->mounted[i]);
2274 } 2274 }
2275 2275
2276 pm_i->parts->pscheme->free(pm_i->parts); 2276 pm_i->parts->pscheme->free(pm_i->parts);
2277 } 2277 }
2278 free(pm_i); 2278 free(pm_i);
2279} 2279}
2280 2280
2281/* Clean up removed devices */ 2281/* Clean up removed devices */
2282static int 2282static int
2283pm_clean(void) 2283pm_clean(void)
2284{ 2284{
2285 int count = 0; 2285 int count = 0;
2286 struct pm_devs *pm_i, *tmp; 2286 struct pm_devs *pm_i, *tmp;
2287 2287
2288 SLIST_FOREACH_SAFE(pm_i, &pm_head, l, tmp) 2288 SLIST_FOREACH_SAFE(pm_i, &pm_head, l, tmp)
2289 if (! pm_i->found) { 2289 if (! pm_i->found) {
2290 count++; 2290 count++;
2291 SLIST_REMOVE(&pm_head, pm_i, pm_devs, l); 2291 SLIST_REMOVE(&pm_head, pm_i, pm_devs, l);
2292 pm_destroy_one(pm_i); 2292 pm_destroy_one(pm_i);
2293 } 2293 }
2294 return count; 2294 return count;
2295} 2295}
2296 2296
2297/* Free all pm storage */ 2297/* Free all pm storage */
2298void 2298void
2299pm_destroy_all(void) 2299pm_destroy_all(void)
2300{ 2300{
2301 struct pm_devs *pm_i, *tmp; 2301 struct pm_devs *pm_i, *tmp;
2302 2302
2303 if (pm_new != pm) 2303 if (pm_new != pm)
2304 pm_destroy_one(pm_new); 2304 pm_destroy_one(pm_new);
2305 SLIST_FOREACH_SAFE(pm_i, &pm_head, l, tmp) { 2305 SLIST_FOREACH_SAFE(pm_i, &pm_head, l, tmp) {
2306 SLIST_REMOVE(&pm_head, pm_i, pm_devs, l); 2306 SLIST_REMOVE(&pm_head, pm_i, pm_devs, l);
2307 pm_destroy_one(pm_i); 2307 pm_destroy_one(pm_i);
2308 } 2308 }
2309} 2309}
2310 2310
2311void 2311void
2312pm_set_lvmpv(struct pm_devs *my_pm, part_id pno, bool add) 2312pm_set_lvmpv(struct pm_devs *my_pm, part_id pno, bool add)
2313{ 2313{
2314 size_t i; 2314 size_t i;
2315 struct disk_part_info info; 2315 struct disk_part_info info;
2316 2316
2317 if (!my_pm->parts->pscheme->get_part_info(my_pm->parts, pno, &info)) 2317 if (!my_pm->parts->pscheme->get_part_info(my_pm->parts, pno, &info))
2318 return; 2318 return;
2319 2319
2320 if (add) { 2320 if (add) {
2321 for (i = 0; i < __arraycount(lvm_pvs); i++) 2321 for (i = 0; i < __arraycount(lvm_pvs); i++)
2322 if (lvm_pvs[i].pm == NULL && lvm_pvs[i].start == 0) 2322 if (lvm_pvs[i].pm == NULL && lvm_pvs[i].start == 0)
2323 break; 2323 break;
2324 if (i >= __arraycount(lvm_pvs)) 2324 if (i >= __arraycount(lvm_pvs))
2325 return; 2325 return;
2326 lvm_pvs[i].pm = my_pm; 2326 lvm_pvs[i].pm = my_pm;
2327 lvm_pvs[i].start = info.start; 2327 lvm_pvs[i].start = info.start;
2328 return; 2328 return;
2329 } else { 2329 } else {
2330 for (i = 0; i < __arraycount(lvm_pvs); i++) 2330 for (i = 0; i < __arraycount(lvm_pvs); i++)
2331 if (lvm_pvs[i].pm == my_pm && 2331 if (lvm_pvs[i].pm == my_pm &&
2332 lvm_pvs[i].start == info.start) 2332 lvm_pvs[i].start == info.start)
2333 break; 2333 break;
2334 if (i >= __arraycount(lvm_pvs)) 2334 if (i >= __arraycount(lvm_pvs))
2335 return; 2335 return;
2336 lvm_pvs[i].pm = NULL; 2336 lvm_pvs[i].pm = NULL;
2337 lvm_pvs[i].start = 0; 2337 lvm_pvs[i].start = 0;
2338 } 2338 }
2339} 2339}
2340 2340
2341bool 2341bool
2342pm_is_lvmpv(struct pm_devs *my_pm, part_id id, 2342pm_is_lvmpv(struct pm_devs *my_pm, part_id id,
2343 const struct disk_part_info *info) 2343 const struct disk_part_info *info)
2344{ 2344{
2345 size_t i; 2345 size_t i;
2346 2346
2347 for (i = 0; i < __arraycount(lvm_pvs); i++) { 2347 for (i = 0; i < __arraycount(lvm_pvs); i++) {
2348 if (lvm_pvs[i].pm != my_pm) 2348 if (lvm_pvs[i].pm != my_pm)
2349 continue; 2349 continue;
2350 if (lvm_pvs[i].start == info->start) 2350 if (lvm_pvs[i].start == info->start)
2351 return true; 2351 return true;
2352 } 2352 }
2353 2353
2354 return false; 2354 return false;
2355} 2355}
2356 2356
2357void 2357void
2358pm_setfstype(struct pm_devs *pm_cur, part_id id, int fstype, int fs_subtype) 2358pm_setfstype(struct pm_devs *pm_cur, part_id id, int fstype, int fs_subtype)
2359{ 2359{
2360 struct disk_part_info info; 2360 struct disk_part_info info;
2361 2361
2362 if (!pm_cur->parts->pscheme->get_part_info(pm_cur->parts, id, &info)) 2362 if (!pm_cur->parts->pscheme->get_part_info(pm_cur->parts, id, &info))
2363 return; 2363 return;
2364 2364
2365 info.nat_type = pm_cur->parts->pscheme->get_fs_part_type(PT_root, 2365 info.nat_type = pm_cur->parts->pscheme->get_fs_part_type(PT_root,
2366 fstype, fs_subtype); 2366 fstype, fs_subtype);
2367 if (info.nat_type == NULL) 2367 if (info.nat_type == NULL)
2368 return; 2368 return;
2369 info.fs_type = fstype; 2369 info.fs_type = fstype;
2370 info.fs_sub_type = fs_subtype; 2370 info.fs_sub_type = fs_subtype;
2371 pm_cur->parts->pscheme->set_part_info(pm_cur->parts, id, &info, NULL); 2371 pm_cur->parts->pscheme->set_part_info(pm_cur->parts, id, &info, NULL);
2372} 2372}
2373 2373
2374static void 2374static void
2375pm_select(struct pm_devs *pm_devs_in) 2375pm_select(struct pm_devs *pm_devs_in)
2376{ 2376{
2377 pm = pm_devs_in; 2377 pm = pm_devs_in;
2378 if (logfp) 2378 if (logfp)
2379 (void)fprintf(logfp, "Partman device: %s\n", pm->diskdev); 2379 (void)fprintf(logfp, "Partman device: %s\n", pm->diskdev);
2380} 2380}
2381 2381
2382void 2382void
2383pm_rename(struct pm_devs *pm_cur) 2383pm_rename(struct pm_devs *pm_cur)
2384{ 2384{
2385#if 0 // XXX - convert to custom attribute or handle similar 2385#if 0 // XXX - convert to custom attribute or handle similar
2386 pm_select(pm_cur); 2386 pm_select(pm_cur);
2387 msg_prompt_win(MSG_packname, -1, 18, 0, 0, pm_cur->bsddiskname, 2387 msg_prompt_win(MSG_packname, -1, 18, 0, 0, pm_cur->bsddiskname,
2388 pm_cur->bsddiskname, sizeof pm_cur->bsddiskname); 2388 pm_cur->bsddiskname, sizeof pm_cur->bsddiskname);
2389#ifndef NO_DISKLABEL 2389#ifndef NO_DISKLABEL
2390 (void) savenewlabel(pm_cur->bsdlabel, MAXPARTITIONS); 2390 (void) savenewlabel(pm_cur->bsdlabel, MAXPARTITIONS);
2391#endif 2391#endif
2392#endif 2392#endif
2393} 2393}
2394 2394
2395int 2395int
2396pm_editpart(int part_num) 2396pm_editpart(int part_num)
2397{ 2397{
2398 struct partition_usage_set pset = {}; 2398 struct partition_usage_set pset = {};
2399 2399
2400 usage_set_from_parts(&pset, pm->parts); 2400 usage_set_from_parts(&pset, pm->parts);
2401 edit_ptn(&(struct menudesc){.cursel = part_num}, &pset); 2401 edit_ptn(&(struct menudesc){.cursel = part_num}, &pset);
2402 free_usage_set(&pset); 2402 free_usage_set(&pset);
2403 if (checkoverlap(pm->parts)) { 2403 if (checkoverlap(pm->parts)) {
2404 hit_enter_to_continue(MSG_cantsave, NULL); 2404 hit_enter_to_continue(MSG_cantsave, NULL);
2405 return -1; 2405 return -1;
2406 } 2406 }
2407 pm->unsaved = 1; 2407 pm->unsaved = 1;
2408 return 0; 2408 return 0;
2409} 2409}
2410 2410
2411/* Safe erase of disk */ 2411/* Safe erase of disk */
2412void 2412void
2413pm_shred(struct part_entry *pe, int shredtype) 2413pm_shred(struct part_entry *pe, int shredtype)
2414{ 2414{
2415 const char *srcdev; 2415 const char *srcdev;
2416 char dev[SSTRSIZE]; 2416 char dev[SSTRSIZE];
2417 struct pm_devs *my_pm; 2417 struct pm_devs *my_pm;
2418 2418
2419 my_pm = pe->dev_ptr; 2419 my_pm = pe->dev_ptr;
2420 if (pe->type == PM_DISK) { 2420 if (pe->type == PM_DISK) {
2421 snprintf(dev, sizeof dev, 2421 snprintf(dev, sizeof dev,
2422 _PATH_DEV "r%s%c", my_pm->diskdev, 'a' + RAW_PART); 2422 _PATH_DEV "r%s%c", my_pm->diskdev, 'a' + RAW_PART);
2423 if (pe->parts != NULL) { 2423 if (pe->parts != NULL) {
2424 pe->parts->pscheme->free(pe->parts); 2424 pe->parts->pscheme->free(pe->parts);
2425 pe->parts = NULL; 2425 pe->parts = NULL;
2426 my_pm->parts = NULL; 2426 my_pm->parts = NULL;
2427 } 2427 }
2428 } else if (pe->type == PM_PART) { 2428 } else if (pe->type == PM_PART) {
2429 pe->parts->pscheme->get_part_device(pe->parts, pe->id, 2429 pe->parts->pscheme->get_part_device(pe->parts, pe->id,
2430 dev, sizeof dev, NULL, raw_dev_name, true, true); 2430 dev, sizeof dev, NULL, raw_dev_name, true, true);
2431 } 2431 }
2432 2432
2433 switch (shredtype) { 2433 switch (shredtype) {
2434 case SHRED_ZEROS: 2434 case SHRED_ZEROS:
2435 srcdev = _PATH_DEVZERO; 2435 srcdev = _PATH_DEVZERO;
2436 break; 2436 break;
2437 case SHRED_RANDOM: 2437 case SHRED_RANDOM:
2438 srcdev = _PATH_URANDOM; 2438 srcdev = _PATH_URANDOM;
2439 break; 2439 break;
2440 default: 2440 default:
2441 return; 2441 return;
2442 } 2442 }
2443 run_program(RUN_DISPLAY | RUN_PROGRESS, 2443 run_program(RUN_DISPLAY | RUN_PROGRESS,
2444 "progress -f %s -b 1m dd bs=1m of=%s", srcdev, dev); 2444 "progress -f %s -b 1m dd bs=1m of=%s", srcdev, dev);
2445 pm_partusage(my_pm, -1, 1); 2445 pm_partusage(my_pm, -1, 1);
2446} 2446}
2447 2447
2448#if 0 // XXX 2448#if 0 // XXX
2449static int 2449static int
2450pm_mountall_sort(const void *a, const void *b) 2450pm_mountall_sort(const void *a, const void *b)
2451{ 2451{
2452 return strcmp(mnts[*(const int *)a].on, mnts[*(const int *)b].on); 2452 return strcmp(mnts[*(const int *)a].on, mnts[*(const int *)b].on);
2453} 2453}
2454#endif 2454#endif
2455 2455
2456#if 0 // XXX 2456#if 0 // XXX
2457/* Mount all available partitions */ 2457/* Mount all available partitions */
2458static int 2458static int
2459pm_mountall(void) 2459pm_mountall(void)
2460{ 2460{
2461 int num_devs = 0; 2461 int num_devs = 0;
2462 int mnts_order[MAX_MNTS]; 2462 int mnts_order[MAX_MNTS];
2463 int i, ii, error, ok; 2463 int i, ii, error, ok;
2464 char dev[SSTRSIZE]; dev[0] = '\0'; 2464 char dev[SSTRSIZE]; dev[0] = '\0';
2465 struct pm_devs *pm_i; 2465 struct pm_devs *pm_i;
2466 2466
2467 localfs_dev[0] = '\0'; 2467 localfs_dev[0] = '\0';
2468 if (mnts == NULL) 2468 if (mnts == NULL)
2469 mnts = calloc(MAX_MNTS, sizeof(*mnts)); 2469 mnts = calloc(MAX_MNTS, sizeof(*mnts));
2470 2470
2471 SLIST_FOREACH(pm_i, &pm_head, l) { 2471 SLIST_FOREACH(pm_i, &pm_head, l) {
2472 ok = 0; 2472 ok = 0;
2473 for (i = 0; i < MAXPARTITIONS; i++) { 2473 for (i = 0; i < MAXPARTITIONS; i++) {
2474 if (!(pm_i->bsdlabel[i].pi_flags & PIF_MOUNT && 2474 if (!(pm_i->bsdlabel[i].pi_flags & PIF_MOUNT &&
2475 pm_i->bsdlabel[i].mnt_opts != NULL)) 2475 pm_i->bsdlabel[i].mnt_opts != NULL))
2476 continue; 2476 continue;
2477 mnts[num_devs].mnt_opts = pm_i->bsdlabel[i].mnt_opts; 2477 mnts[num_devs].mnt_opts = pm_i->bsdlabel[i].mnt_opts;
2478 if (strlen(pm_i->bsdlabel[i].mounted) > 0) { 2478 if (strlen(pm_i->bsdlabel[i].mounted) > 0) {
2479 /* Device is already mounted. So, doing mount_null */ 2479 /* Device is already mounted. So, doing mount_null */
2480 strlcpy(mnts[num_devs].dev, pm_i->bsdlabel[i].mounted, MOUNTLEN); 2480 strlcpy(mnts[num_devs].dev, pm_i->bsdlabel[i].mounted, MOUNTLEN);
2481 mnts[num_devs].mnt_opts = "-t null"; 2481 mnts[num_devs].mnt_opts = "-t null";
2482 } else { 2482 } else {
2483 pm_getdevstring(dev, SSTRSIZE, pm_i, i); 2483 pm_getdevstring(dev, SSTRSIZE, pm_i, i);
2484 snprintf(mnts[num_devs].dev, STRSIZE, "/dev/%s", dev); 2484 snprintf(mnts[num_devs].dev, STRSIZE, "/dev/%s", dev);
2485 } 2485 }
2486 mnts[num_devs].on = pm_i->bsdlabel[i].pi_mount; 2486 mnts[num_devs].on = pm_i->bsdlabel[i].pi_mount;
2487 if (strcmp(pm_i->bsdlabel[i].pi_mount, "/") == 0) { 2487 if (strcmp(pm_i->bsdlabel[i].pi_mount, "/") == 0) {
2488 /* Use disk with / as a default if the user has 2488 /* Use disk with / as a default if the user has
2489 the sets on a local disk */ 2489 the sets on a local disk */
2490 strlcpy(localfs_dev, pm_i->diskdev, SSTRSIZE); 2490 strlcpy(localfs_dev, pm_i->diskdev, SSTRSIZE);
2491 } 2491 }
2492 num_devs++; 2492 num_devs++;
2493 ok = 1; 2493 ok = 1;
2494 } 2494 }
2495 if (ok) 2495 if (ok)
2496 md_pre_mount(NULL, 0); 2496 md_pre_mount(NULL, 0);
2497 } 2497 }
2498 if (strlen(localfs_dev) < 1) { 2498 if (strlen(localfs_dev) < 1) {
2499 hit_enter_to_continue(MSG_noroot, NULL); 2499 hit_enter_to_continue(MSG_noroot, NULL);
2500 return -1; 2500 return -1;
2501 } 2501 }
2502 for (i = 0; i < num_devs; i++) 2502 for (i = 0; i < num_devs; i++)
2503 mnts_order[i] = i; 2503 mnts_order[i] = i;
2504 qsort(mnts_order, num_devs, sizeof mnts_order[0], pm_mountall_sort); 2504 qsort(mnts_order, num_devs, sizeof mnts_order[0], pm_mountall_sort);
2505 2505
2506 for (i = 0; i < num_devs; i++) { 2506 for (i = 0; i < num_devs; i++) {
2507 ii = mnts_order[i]; 2507 ii = mnts_order[i];
2508 make_target_dir(mnts[ii].on); 2508 make_target_dir(mnts[ii].on);
2509 error = target_mount_do(mnts[ii].mnt_opts, mnts[ii].dev, mnts[ii].on); 2509 error = target_mount_do(mnts[ii].mnt_opts, mnts[ii].dev, mnts[ii].on);
2510 if (error) 2510 if (error)
2511 return error; 2511 return error;
2512 } 2512 }
2513 return 0; 2513 return 0;
2514} 2514}
2515#endif 2515#endif
2516 2516
2517/* Mount partition bypassing ordinary order */ 2517/* Mount partition bypassing ordinary order */
2518static int 2518static int
2519pm_mount(struct pm_devs *pm_cur, int part_num) 2519pm_mount(struct pm_devs *pm_cur, int part_num)
2520{ 2520{
2521 int error = 0; 2521 int error = 0;
2522#if 0 // XXX 2522#if 0 // XXX
2523 char buf[MOUNTLEN]; 2523 char buf[MOUNTLEN];
2524 2524
2525 if (strlen(pm_cur->bsdlabel[part_num].mounted) > 0) 2525 if (strlen(pm_cur->bsdlabel[part_num].mounted) > 0)
2526 return 0; 2526 return 0;
2527 2527
2528 snprintf(buf, sizeof(buf), "/tmp/%s%c", pm_cur->diskdev, 2528 snprintf(buf, sizeof(buf), "/tmp/%s%c", pm_cur->diskdev,
2529 part_num + 'a'); 2529 part_num + 'a');
2530 if (! dir_exists_p(buf)) 2530 if (! dir_exists_p(buf))
2531 run_program(RUN_DISPLAY | RUN_PROGRESS, "/bin/mkdir -p %s", buf); 2531 run_program(RUN_DISPLAY | RUN_PROGRESS, "/bin/mkdir -p %s", buf);
2532 if (pm_cur->bsdlabel[part_num].pi_flags & PIF_MOUNT && 2532 if (pm_cur->bsdlabel[part_num].pi_flags & PIF_MOUNT &&
2533 pm_cur->bsdlabel[part_num].mnt_opts != NULL && 2533 pm_cur->bsdlabel[part_num].mnt_opts != NULL &&
2534 strlen(pm_cur->bsdlabel[part_num].mounted) < 1) 2534 strlen(pm_cur->bsdlabel[part_num].mounted) < 1)
2535 error += run_program(RUN_DISPLAY | RUN_PROGRESS, "/sbin/mount %s /dev/%s%c %s", 2535 error += run_program(RUN_DISPLAY | RUN_PROGRESS, "/sbin/mount %s /dev/%s%c %s",
2536 pm_cur->bsdlabel[part_num].mnt_opts, 2536 pm_cur->bsdlabel[part_num].mnt_opts,
2537 pm_cur->diskdev, part_num + 'a', buf); 2537 pm_cur->diskdev, part_num + 'a', buf);
2538 2538
2539 if (error) 2539 if (error)
2540 pm_cur->bsdlabel[part_num].mounted[0] = '\0'; 2540 pm_cur->bsdlabel[part_num].mounted[0] = '\0';
2541 else { 2541 else {
2542 strlcpy(pm_cur->bsdlabel[part_num].mounted, buf, MOUNTLEN); 2542 strlcpy(pm_cur->bsdlabel[part_num].mounted, buf, MOUNTLEN);
2543 pm_cur->blocked++; 2543 pm_cur->blocked++;
2544 } 2544 }
2545#endif 2545#endif
2546 return error; 2546 return error;
2547} 2547}
2548 2548
2549void 2549void
2550pm_umount(struct pm_devs *pm_cur, int part_num) 2550pm_umount(struct pm_devs *pm_cur, int part_num)
2551{ 2551{
2552 char buf[SSTRSIZE]; buf[0] = '\0'; 2552 char buf[SSTRSIZE]; buf[0] = '\0';
2553 part_id id; 2553 part_id id;
2554 2554
2555 if (part_num < 0) 2555 if (part_num < 0)
2556 return; 2556 return;
2557 id = (part_id)part_num; 2557 id = (part_id)part_num;
2558 2558
2559 pm_cur->parts->pscheme->get_part_device(pm_cur->parts, id, buf, 2559 pm_cur->parts->pscheme->get_part_device(pm_cur->parts, id, buf,
2560 sizeof buf, NULL, plain_name, false, true); 2560 sizeof buf, NULL, plain_name, false, true);
2561 2561
2562 if (run_program(RUN_DISPLAY | RUN_PROGRESS, 2562 if (run_program(RUN_DISPLAY | RUN_PROGRESS,
2563 "umount -f /dev/%s", buf) == 0) { 2563 "umount -f /dev/%s", buf) == 0) {
2564 free(pm_cur->mounted[id]); 2564 free(pm_cur->mounted[id]);
2565 pm_cur->mounted[id] = NULL; 2565 pm_cur->mounted[id] = NULL;
2566 if (pm_cur->blocked > 0) 2566 if (pm_cur->blocked > 0)
2567 pm_cur->blocked--; 2567 pm_cur->blocked--;
2568 } 2568 }
2569} 2569}
2570 2570
2571int 2571int
2572pm_unconfigure(struct pm_devs *pm_cur) 2572pm_unconfigure(struct pm_devs *pm_cur)
2573{ 2573{
2574 int error = 0; 2574 int error = 0;
2575 if (! strncmp(pm_cur->diskdev, "cgd", 3)) { 2575 if (! strncmp(pm_cur->diskdev, "cgd", 3)) {
2576 error = run_program(RUN_DISPLAY | RUN_PROGRESS, "cgdconfig -u %s", pm_cur->diskdev); 2576 error = run_program(RUN_DISPLAY | RUN_PROGRESS, "cgdconfig -u %s", pm_cur->diskdev);
2577 if (! error && pm_cur->refdev != NULL) { 2577 if (! error && pm_cur->refdev != NULL) {
2578 ((struct cgd_desc*)pm_cur->refdev)->pm->blocked--; 2578 ((struct cgd_desc*)pm_cur->refdev)->pm->blocked--;
2579 ((struct cgd_desc*)pm_cur->refdev)->blocked = 0; 2579 ((struct cgd_desc*)pm_cur->refdev)->blocked = 0;
2580 } 2580 }
2581 } else if (! strncmp(pm_cur->diskdev, "vnd", 3)) { 2581 } else if (! strncmp(pm_cur->diskdev, "vnd", 3)) {
2582 error = run_program(RUN_DISPLAY | RUN_PROGRESS, "vndconfig -u %s", pm_cur->diskdev); 2582 error = run_program(RUN_DISPLAY | RUN_PROGRESS, "vndconfig -u %s", pm_cur->diskdev);
2583 if (! error && pm_cur->refdev != NULL) { 2583 if (! error && pm_cur->refdev != NULL) {
2584 ((struct vnd_desc*)pm_cur->refdev)->pm->blocked--; 2584 ((struct vnd_desc*)pm_cur->refdev)->pm->blocked--;
2585 ((struct vnd_desc*)pm_cur->refdev)->blocked = 0; 2585 ((struct vnd_desc*)pm_cur->refdev)->blocked = 0;
2586 } 2586 }
2587 } else if (! strncmp(pm_cur->diskdev, "raid", 4)) { 2587 } else if (! strncmp(pm_cur->diskdev, "raid", 4)) {
2588 error = run_program(RUN_DISPLAY | RUN_PROGRESS, "raidctl -u %s", pm_cur->diskdev); 2588 error = run_program(RUN_DISPLAY | RUN_PROGRESS, "raidctl -u %s", pm_cur->diskdev);
2589 if (! error && pm_cur->refdev != NULL) { 2589 if (! error && pm_cur->refdev != NULL) {
2590 ((struct raid_desc*)pm_cur->refdev)->blocked = 0; 2590 ((struct raid_desc*)pm_cur->refdev)->blocked = 0;
2591#if 0 // XXX 2591#if 0 // XXX
2592 for (i = 0; i < MAX_IN_RAID; i++) 2592 for (i = 0; i < MAX_IN_RAID; i++)
2593 if (((struct raid_desc*)pm_cur->refdev)->comp[i].parts != NULL) 2593 if (((struct raid_desc*)pm_cur->refdev)->comp[i].parts != NULL)
2594 ((raids_t*)pm_cur->refdev)->pm[i]->blocked--; 2594 ((raids_t*)pm_cur->refdev)->pm[i]->blocked--;
2595#endif 2595#endif
2596 } 2596 }
2597 } else if (! strncmp(pm_cur->diskdev, "dk", 2)) { 2597 } else if (! strncmp(pm_cur->diskdev, "dk", 2)) {
2598 if (pm_cur->refdev == NULL) 2598 if (pm_cur->refdev == NULL)
2599 return -2; 2599 return -2;
2600 /* error = */ 2600 /* error = */
2601 run_program(RUN_DISPLAY | RUN_PROGRESS, "dkctl %s delwedge %s", 2601 run_program(RUN_DISPLAY | RUN_PROGRESS, "dkctl %s delwedge %s",
2602 ((struct pm_devs*)pm_cur->refdev)->diskdev, pm_cur->diskdev); 2602 ((struct pm_devs*)pm_cur->refdev)->diskdev, pm_cur->diskdev);
2603#if 0 // XXX 2603#if 0 // XXX
2604 if (! error) { 2604 if (! error) {
2605 if (pm_cur->refdev != NULL && ((struct pm_devs*)pm_cur->refdev)->blocked > 0) 2605 if (pm_cur->refdev != NULL && ((struct pm_devs*)pm_cur->refdev)->blocked > 0)
2606 ((struct pm_devs*)pm_cur->refdev)->blocked--; 2606 ((struct pm_devs*)pm_cur->refdev)->blocked--;
2607 sscanf(pm_cur->diskdev, "dk%d", &num); 2607 sscanf(pm_cur->diskdev, "dk%d", &num);
2608 if (num >= 0 && num < MAX_WEDGES) 2608 if (num >= 0 && num < MAX_WEDGES)
2609 wedges[num].allocated = 0; 2609 wedges[num].allocated = 0;
2610 } 2610 }
2611#endif 2611#endif
2612 } /* XXX: lvm */ 2612 } /* XXX: lvm */
2613 else 2613 else
2614 error = run_program(RUN_DISPLAY | RUN_PROGRESS, "eject -t disk /dev/%sd", 2614 error = run_program(RUN_DISPLAY | RUN_PROGRESS, "eject -t disk /dev/%sd",
2615 pm_cur->diskdev); 2615 pm_cur->diskdev);
2616 if (!error) 2616 if (!error)
2617 pm_cur->found = 0; 2617 pm_cur->found = 0;
2618 return error; 2618 return error;
2619} 2619}
2620 2620
2621/* Last checks before leaving partition manager */ 2621/* Last checks before leaving partition manager */
2622#if 0 2622#if 0
2623static int 2623static int
2624pm_lastcheck(void) 2624pm_lastcheck(void)
2625{ 2625{
2626 FILE *file_tmp = fopen(concat_paths(targetroot_mnt, "/etc/fstab"), "r"); 2626 FILE *file_tmp = fopen(concat_paths(targetroot_mnt, "/etc/fstab"), "r");
2627 if (file_tmp == NULL) 2627 if (file_tmp == NULL)
2628 return 1; 2628 return 1;
2629 fclose(file_tmp); 2629 fclose(file_tmp);
2630 return 0; 2630 return 0;
2631} 2631}
2632#endif 2632#endif
2633 2633
2634/* Are there unsaved changes? */ 2634/* Are there unsaved changes? */
2635static int 2635static int
2636pm_needsave(void) 2636pm_needsave(void)
2637{ 2637{
2638 struct pm_devs *pm_i; 2638 struct pm_devs *pm_i;
2639 SLIST_FOREACH(pm_i, &pm_head, l) 2639 SLIST_FOREACH(pm_i, &pm_head, l)
2640 if (pm_i->unsaved) { 2640 if (pm_i->unsaved) {
2641 /* Oops, we have unsaved changes */ 2641 /* Oops, we have unsaved changes */
2642 pm_changed = 1; 2642 pm_changed = 1;
2643 msg_display(MSG_saveprompt); 2643 msg_display(MSG_saveprompt);
2644 return ask_yesno(NULL); 2644 return ask_yesno(NULL);
2645 } 2645 }
2646 return 0; 2646 return 0;
2647} 2647}
2648 2648
2649/* Write all changes to disk */ 2649/* Write all changes to disk */
2650static int 2650static int
2651pm_commit(menudesc *m, void *arg) 2651pm_commit(menudesc *m, void *arg)
2652{ 2652{
2653 int retcode; 2653 int retcode;
2654 struct pm_devs *pm_i; 2654 struct pm_devs *pm_i;
2655 struct disk_partitions *secondary; 2655 struct disk_partitions *secondary;
2656 2656
2657 pm_retvalue = -1; 2657 pm_retvalue = -1;
2658 SLIST_FOREACH(pm_i, &pm_head, l) { 2658 SLIST_FOREACH(pm_i, &pm_head, l) {
2659 if (! pm_i->unsaved) 2659 if (! pm_i->unsaved)
2660 continue; 2660 continue;
2661 if (pm_i->parts == NULL) { 2661 if (pm_i->parts == NULL) {
2662 pm_i->unsaved = false; 2662 pm_i->unsaved = false;
2663 continue; 2663 continue;
2664 } 2664 }
2665 if (!pm_i->parts->pscheme->write_to_disk(pm_i->parts)) { 2665 if (!pm_i->parts->pscheme->write_to_disk(pm_i->parts)) {
2666 if (logfp) 2666 if (logfp)
2667 fprintf(logfp, "partitining error %s\n", 2667 fprintf(logfp, "partitining error %s\n",
2668 pm_i->diskdev); 2668 pm_i->diskdev);
2669 return -1; 2669 return -1;
2670 } 2670 }
2671 if (pm_i->parts->pscheme->secondary_scheme != NULL) { 2671 if (pm_i->parts->pscheme->secondary_scheme != NULL) {
2672 secondary = pm_i->parts->pscheme-> 2672 secondary = pm_i->parts->pscheme->
2673 secondary_partitions(pm_i->parts, -1, false); 2673 secondary_partitions(pm_i->parts, -1, false);
2674 if (secondary != NULL) { 2674 if (secondary != NULL) {
2675 if (!secondary->pscheme->write_to_disk( 2675 if (!secondary->pscheme->write_to_disk(
2676 secondary)) { 2676 secondary)) {
2677 if (logfp) 2677 if (logfp)
2678 fprintf(logfp, 2678 fprintf(logfp,
2679 "partitining error %s\n", 2679 "partitining error %s\n",
2680 pm_i->diskdev); 2680 pm_i->diskdev);
2681 return -1; 2681 return -1;
2682 } 2682 }
2683 } 2683 }
2684 } 2684 }
2685 } 2685 }
2686 2686
2687 /* Call all functions that may create new devices */ 2687 /* Call all functions that may create new devices */
2688 if ((retcode = pm_raid_commit()) != 0) { 2688 if ((retcode = pm_raid_commit()) != 0) {
2689 if (logfp) 2689 if (logfp)
2690 fprintf(logfp, "RAIDframe configuring error #%d\n", retcode); 2690 fprintf(logfp, "RAIDframe configuring error #%d\n", retcode);
2691 return -1; 2691 return -1;
2692 } 2692 }
2693 if ((retcode = pm_cgd_commit()) != 0) { 2693 if ((retcode = pm_cgd_commit()) != 0) {
2694 if (logfp) 2694 if (logfp)
2695 fprintf(logfp, "CGD configuring error #%d\n", retcode); 2695 fprintf(logfp, "CGD configuring error #%d\n", retcode);
2696 return -1; 2696 return -1;
2697 } 2697 }
2698 if ((retcode = pm_lvm_commit()) != 0) { 2698 if ((retcode = pm_lvm_commit()) != 0) {
2699 if (logfp) 2699 if (logfp)
2700 fprintf(logfp, "LVM configuring error #%d\n", retcode); 2700 fprintf(logfp, "LVM configuring error #%d\n", retcode);
2701 return -1; 2701 return -1;
2702 } 2702 }
2703 if ((retcode = pm_vnd_commit()) != 0) { 2703 if ((retcode = pm_vnd_commit()) != 0) {
2704 if (logfp) 2704 if (logfp)
2705 fprintf(logfp, "VND configuring error #%d\n", retcode); 2705 fprintf(logfp, "VND configuring error #%d\n", retcode);
2706 return -1; 2706 return -1;
2707 } 2707 }
2708 if (m != NULL && arg != NULL) 2708 if (m != NULL && arg != NULL)
2709 pm_upddevlist(m, arg); 2709 pm_upddevlist(m, arg);
2710 if (logfp) 2710 if (logfp)
2711 fflush (logfp); 2711 fflush (logfp);
2712 2712
2713 pm_retvalue = 0; 2713 pm_retvalue = 0;
2714 return 0; 2714 return 0;
2715} 2715}
2716 2716
2717#if 0 // XXX 2717#if 0 // XXX
2718static int 2718static int
2719pm_savebootsector(void) 2719pm_savebootsector(void)
2720{ 2720{
2721 struct pm_devs *pm_i; 2721 struct pm_devs *pm_i;
2722 SLIST_FOREACH(pm_i, &pm_head, l) 2722 SLIST_FOREACH(pm_i, &pm_head, l)
2723 if (pm_i->bootable) { 2723 if (pm_i->bootable) {
2724 if (! strncmp("raid", pm_i->diskdev, 4)) 2724 if (! strncmp("raid", pm_i->diskdev, 4))
2725 if (run_program(RUN_DISPLAY | RUN_PROGRESS, 2725 if (run_program(RUN_DISPLAY | RUN_PROGRESS,
2726 "raidctl -v -A root %s", pm_i->diskdev) != 0) { 2726 "raidctl -v -A root %s", pm_i->diskdev) != 0) {
2727 if (logfp) 2727 if (logfp)
2728 fprintf(logfp, "Error writting RAID bootsector to %s\n", 2728 fprintf(logfp, "Error writting RAID bootsector to %s\n",
2729 pm_i->diskdev); 2729 pm_i->diskdev);
2730 continue; 2730 continue;
2731 } 2731 }
2732 if (pm_i->no_part) { 2732 if (pm_i->no_part) {
2733 if (pm_i->rootpart < 0 || 2733 if (pm_i->rootpart < 0 ||
2734 run_program(RUN_DISPLAY | RUN_PROGRESS, 2734 run_program(RUN_DISPLAY | RUN_PROGRESS,
2735 "gpt biosboot -i %d %s", 2735 "gpt biosboot -i %d %s",
2736 pm_i->rootpart + 1, pm_i->diskdev) != 0) { 2736 pm_i->rootpart + 1, pm_i->diskdev) != 0) {
2737 if (logfp) 2737 if (logfp)
2738 fprintf(logfp, "Error writting GPT bootsector to %s\n", 2738 fprintf(logfp, "Error writting GPT bootsector to %s\n",
2739 pm_i->diskdev); 2739 pm_i->diskdev);
2740 continue; 2740 continue;
2741 } 2741 }
2742 } else { 2742 } else {
2743 pm_select(pm_i); 2743 pm_select(pm_i);
2744 if ( 2744 if (
2745#ifndef NO_DISKLABEL 2745#ifndef NO_DISKLABEL
2746 !check_partitions(pm_i, pm_i->parts) || 2746 !check_partitions(pm_i, pm_i->parts) ||
2747#endif 2747#endif
2748 md_post_newfs() != 0) { 2748 md_post_newfs() != 0) {
2749 if (logfp) 2749 if (logfp)
2750 fprintf(logfp, "Error writting bootsector to %s\n", 2750 fprintf(logfp, "Error writting bootsector to %s\n",
2751 pm_i->diskdev); 2751 pm_i->diskdev);
2752 continue; 2752 continue;
2753 } 2753 }
2754 } 2754 }
2755 } 2755 }
2756 return 0; 2756 return 0;
2757} 2757}
2758#endif 2758#endif
2759 2759
2760/* Function for 'Enter'-menu */ 2760/* Function for 'Enter'-menu */
2761static int 2761static int
2762pm_submenu(menudesc *m, void *arg) 2762pm_submenu(menudesc *m, void *arg)
2763{ 2763{
2764 struct pm_devs *pm_cur = NULL; 2764 struct pm_devs *pm_cur = NULL;
2765 pm_retvalue = m->cursel + 1; 2765 pm_retvalue = m->cursel + 1;
2766 struct part_entry *cur_pe = (struct part_entry *)arg + m->cursel; 2766 struct part_entry *cur_pe = (struct part_entry *)arg + m->cursel;
2767 2767
2768 switch (cur_pe->type) { 2768 switch (cur_pe->type) {
2769 case PM_DISK: 2769 case PM_DISK:
2770 case PM_PART: 2770 case PM_PART:
2771 case PM_SPEC: 2771 case PM_SPEC:
2772 if (cur_pe->dev_ptr != NULL) { 2772 if (cur_pe->dev_ptr != NULL) {
2773 pm_cur = cur_pe->dev_ptr; 2773 pm_cur = cur_pe->dev_ptr;
2774 if (pm_cur == NULL) 2774 if (pm_cur == NULL)
2775 return -1; 2775 return -1;
2776 if (pm_cur->blocked) { 2776 if (pm_cur->blocked) {
2777 clear(); 2777 clear();
2778 refresh(); 2778 refresh();
2779 msg_display(MSG_wannaunblock); 2779 msg_display(MSG_wannaunblock);
2780 if (!ask_noyes(NULL)) 2780 if (!ask_noyes(NULL))
2781 return -2; 2781 return -2;
2782 pm_cur->blocked = 0; 2782 pm_cur->blocked = 0;
2783 } 2783 }
2784 pm_select(pm_cur); 2784 pm_select(pm_cur);
2785 } 2785 }
2786 default: 2786 default:
2787 break; 2787 break;
2788 } 2788 }
2789 2789
2790 switch (cur_pe->type) { 2790 switch (cur_pe->type) {
2791 case PM_DISK: 2791 case PM_DISK:
2792 process_menu(MENU_pmdiskentry, cur_pe); 2792 process_menu(MENU_pmdiskentry, cur_pe);
2793 break; 2793 break;
2794 case PM_PART: 2794 case PM_PART:
2795 process_menu(MENU_pmpartentry, cur_pe); 2795 process_menu(MENU_pmpartentry, cur_pe);
2796 break; 2796 break;
2797 case PM_SPEC: 2797 case PM_SPEC:
2798 process_menu(MENU_pmpartentry, cur_pe); 2798 process_menu(MENU_pmpartentry, cur_pe);
2799 break; 2799 break;
2800 case PM_RAID: 2800 case PM_RAID:
2801 pm_edit(PMR_MENU_END, pm_raid_edit_menufmt, 2801 pm_edit(PMR_MENU_END, pm_raid_edit_menufmt,
2802 pm_raid_set_value, pm_raid_check, pm_raid_init, 2802 pm_raid_set_value, pm_raid_check, pm_raid_init,
2803 NULL, cur_pe->dev_ptr, 0, &raids_t_info); 2803 NULL, cur_pe->dev_ptr, 0, &raids_t_info);
2804 break; 2804 break;
2805 case PM_VND: 2805 case PM_VND:
2806 return pm_edit(PMV_MENU_END, pm_vnd_edit_menufmt, 2806 return pm_edit(PMV_MENU_END, pm_vnd_edit_menufmt,
2807 pm_vnd_set_value, pm_vnd_check, pm_vnd_init, 2807 pm_vnd_set_value, pm_vnd_check, pm_vnd_init,
2808 NULL, cur_pe->dev_ptr, 0, &vnds_t_info); 2808 NULL, cur_pe->dev_ptr, 0, &vnds_t_info);
2809 case PM_CGD: 2809 case PM_CGD:
2810 pm_cgd_edit_old(cur_pe); 2810 pm_cgd_edit_old(cur_pe);
2811 break; 2811 break;
2812 case PM_LVM: 2812 case PM_LVM:
2813 return pm_edit(PML_MENU_END, pm_lvm_edit_menufmt, 2813 return pm_edit(PML_MENU_END, pm_lvm_edit_menufmt,
2814 pm_lvm_set_value, pm_lvm_check, pm_lvm_init, 2814 pm_lvm_set_value, pm_lvm_check, pm_lvm_init,
2815 NULL, cur_pe->dev_ptr, 0, &lvms_t_info); 2815 NULL, cur_pe->dev_ptr, 0, &lvms_t_info);
2816 case PM_LVMLV: 2816 case PM_LVMLV:
2817 return pm_edit(PMLV_MENU_END, pm_lvmlv_edit_menufmt, 2817 return pm_edit(PMLV_MENU_END, pm_lvmlv_edit_menufmt,
2818 pm_lvmlv_set_value, pm_lvmlv_check, pm_lvmlv_init, 2818 pm_lvmlv_set_value, pm_lvmlv_check, pm_lvmlv_init,
2819 NULL, cur_pe->dev_ptr, 2819 NULL, cur_pe->dev_ptr,
2820 cur_pe->dev_ptr_delta, &lv_t_info); 2820 cur_pe->dev_ptr_delta, &lv_t_info);
2821 } 2821 }
2822 return 0; 2822 return 0;
2823} 2823}
2824 2824
2825/* Functions that generate menu entries text */ 2825/* Functions that generate menu entries text */
2826static void 2826static void
2827pm_menufmt(menudesc *m, int opt, void *arg) 2827pm_menufmt(menudesc *m, int opt, void *arg)
2828{ 2828{
2829 const char *dev_status = ""; 2829 const char *dev_status = "";
2830 char buf[STRSIZE], dev[STRSIZE]; 2830 char buf[STRSIZE], dev[STRSIZE];
2831 part_id part_num = ((struct part_entry *)arg)[opt].id; 2831 part_id part_num = ((struct part_entry *)arg)[opt].id;
2832 struct pm_devs *pm_cur = ((struct part_entry *)arg)[opt].dev_ptr; 2832 struct pm_devs *pm_cur = ((struct part_entry *)arg)[opt].dev_ptr;
2833 struct disk_partitions *parts = ((struct part_entry *)arg)[opt].parts; 2833 struct disk_partitions *parts = ((struct part_entry *)arg)[opt].parts;
2834 struct disk_part_info info; 2834 struct disk_part_info info;
2835 const char *mount_point, *fstype; 2835 const char *mount_point, *fstype;
2836 2836
2837 switch (((struct part_entry *)arg)[opt].type) { 2837 switch (((struct part_entry *)arg)[opt].type) {
2838 case PM_DISK: 2838 case PM_DISK:
2839 if (pm_cur->blocked) 2839 if (pm_cur->blocked)
2840 dev_status = msg_string(MSG_pmblocked); 2840 dev_status = msg_string(MSG_pmblocked);
2841 else if (! pm_cur->unsaved) 2841 else if (! pm_cur->unsaved)
2842 dev_status = msg_string(MSG_pmunchanged); 2842 dev_status = msg_string(MSG_pmunchanged);
2843 else 2843 else
2844 dev_status = msg_string(MSG_pmused); 2844 dev_status = msg_string(MSG_pmused);
2845 wprintw(m->mw, "%-43.42s %25.24s", 2845 wprintw(m->mw, "%-43.42s %25.24s",
2846 pm_cur->diskdev_descr, 2846 pm_cur->diskdev_descr,
2847 dev_status); 2847 dev_status);
2848 break; 2848 break;
2849 case PM_PART: 2849 case PM_PART:
2850 if (parts->pscheme->get_part_device != NULL) 2850 if (parts->pscheme->get_part_device == NULL ||
2851 parts->pscheme->get_part_device( 2851 !parts->pscheme->get_part_device(
2852 parts, part_num, 2852 parts, part_num,
2853 dev, sizeof dev, NULL, plain_name, false, 2853 dev, sizeof dev, NULL, plain_name, false,
2854 true); 2854 true))
2855 else 2855 strcpy(dev, "-");
2856 strcpy(dev, "-"); 2856
2857 parts->pscheme->get_part_info(parts, 2857 parts->pscheme->get_part_info(parts,
2858 part_num, &info); 2858 part_num, &info);
2859 if (pm_cur->mounted != NULL && 2859 if (pm_cur->mounted != NULL &&
2860 pm_cur->mounted[part_num] != NULL && 2860 pm_cur->mounted[part_num] != NULL &&
2861 pm_cur->mounted[part_num][0] != 0) 2861 pm_cur->mounted[part_num][0] != 0)
2862 mount_point = msg_string(MSG_pmmounted); 2862 mount_point = msg_string(MSG_pmmounted);
2863 else 2863 else
2864 mount_point = msg_string(MSG_pmunused); 2864 mount_point = msg_string(MSG_pmunused);
2865 fstype = getfslabelname(info.fs_type, 2865 fstype = getfslabelname(info.fs_type,
2866 info.fs_sub_type); 2866 info.fs_sub_type);
2867 if (info.last_mounted != NULL) { 2867 if (info.last_mounted != NULL) {
2868 snprintf(buf, STRSIZE, "%s (%s) %s", 2868 snprintf(buf, STRSIZE, "%s (%s) %s",
2869 info.last_mounted, fstype, 2869 info.last_mounted, fstype,
2870 mount_point); 2870 mount_point);
2871 pm_fmt_disk_line(m->mw, dev, buf, 2871 pm_fmt_disk_line(m->mw, dev, buf,
2872 info.size, NULL); 2872 info.size, NULL);
2873 } else { 2873 } else {
2874 if (fstype != NULL) { 2874 if (fstype != NULL) {
2875 strlcat(dev, " (", sizeof(dev)); 2875 strlcat(dev, " (", sizeof(dev));
2876 strlcat(dev, fstype, sizeof(dev)); 2876 strlcat(dev, fstype, sizeof(dev));
2877 strlcat(dev, ")", sizeof(dev)); 2877 strlcat(dev, ")", sizeof(dev));
2878 } 2878 }
2879 pm_fmt_disk_line(m->mw, dev, NULL, 2879 pm_fmt_disk_line(m->mw, dev, NULL,
2880 info.size, NULL); 2880 info.size, NULL);
2881 } 2881 }
2882 break; 2882 break;
2883 case PM_SPEC: 2883 case PM_SPEC:
2884 /* XXX ? */ 2884 /* XXX ? */
2885 pm_fmt_disk_line(m->mw, pm_cur->diskdev_descr, NULL, 2885 pm_fmt_disk_line(m->mw, pm_cur->diskdev_descr, NULL,
2886 pm_cur->dlsize, NULL); 2886 pm_cur->dlsize, NULL);
2887 break; 2887 break;
2888 case PM_RAID: 2888 case PM_RAID:
2889 pm_raid_menufmt(m, opt, arg); 2889 pm_raid_menufmt(m, opt, arg);
2890 break; 2890 break;
2891 case PM_VND: 2891 case PM_VND:
2892 pm_vnd_menufmt(m, opt, arg); 2892 pm_vnd_menufmt(m, opt, arg);
2893 break; 2893 break;
2894 case PM_CGD: 2894 case PM_CGD:
2895 pm_cgd_menufmt(m, opt, arg); 2895 pm_cgd_menufmt(m, opt, arg);
2896 break; 2896 break;
2897 case PM_LVM: 2897 case PM_LVM:
2898 pm_lvm_menufmt(m, opt, arg); 2898 pm_lvm_menufmt(m, opt, arg);
2899 break; 2899 break;
2900 case PM_LVMLV: 2900 case PM_LVMLV:
2901 pm_lvmlv_menufmt(m, opt, arg); 2901 pm_lvmlv_menufmt(m, opt, arg);
2902 break; 2902 break;
2903 } 2903 }
2904} 2904}
2905 2905
2906/* Submenu for RAID/LVM/CGD/VND */ 2906/* Submenu for RAID/LVM/CGD/VND */
2907static void 2907static void
2908pm_upddevlist_adv(menudesc *m, void *arg, int *i, 2908pm_upddevlist_adv(menudesc *m, void *arg, int *i,
2909 pm_upddevlist_adv_t *d) 2909 pm_upddevlist_adv_t *d)
2910{ 2910{
2911 int ii; 2911 int ii;
2912 if (d->create_msg != NULL) { 2912 if (d->create_msg != NULL) {
2913 /* We want to have menu entry that creates a new device */ 2913 /* We want to have menu entry that creates a new device */
2914 ((struct part_entry *)arg)[*i].type = d->pe_type; 2914 ((struct part_entry *)arg)[*i].type = d->pe_type;
2915 ((struct part_entry *)arg)[*i].dev_ptr = NULL; 2915 ((struct part_entry *)arg)[*i].dev_ptr = NULL;
2916 ((struct part_entry *)arg)[*i].dev_ptr_delta = d->s->parent_size * d->sub_num; 2916 ((struct part_entry *)arg)[*i].dev_ptr_delta = d->s->parent_size * d->sub_num;
2917 m->opts[(*i)++] = (struct menu_ent) { 2917 m->opts[(*i)++] = (struct menu_ent) {
2918 .opt_name = d->create_msg, 2918 .opt_name = d->create_msg,
2919 .opt_action = pm_submenu, 2919 .opt_action = pm_submenu,
2920 }; 2920 };
2921 } 2921 }
2922 for (ii = 0; ii < d->s->max; ii++) { 2922 for (ii = 0; ii < d->s->max; ii++) {
2923 if (d->s->entry_enabled == NULL || 2923 if (d->s->entry_enabled == NULL ||
2924 d->s->entry_blocked == NULL || 2924 d->s->entry_blocked == NULL ||
2925 *(int*)((char*)d->s->entry_enabled + d->s->entry_size * ii + 2925 *(int*)((char*)d->s->entry_enabled + d->s->entry_size * ii +
2926 d->s->parent_size * d->sub_num) == 0 || 2926 d->s->parent_size * d->sub_num) == 0 ||
2927 *(int*)((char*)d->s->entry_blocked + d->s->entry_size * ii + 2927 *(int*)((char*)d->s->entry_blocked + d->s->entry_size * ii +
2928 d->s->parent_size * d->sub_num) != 0) 2928 d->s->parent_size * d->sub_num) != 0)
2929 continue; 2929 continue;
2930 /* We have a entry for displaying */ 2930 /* We have a entry for displaying */
2931 pm_changed = 1; 2931 pm_changed = 1;
2932 m->opts[*i] = (struct menu_ent) { 2932 m->opts[*i] = (struct menu_ent) {
2933 .opt_name = NULL, 2933 .opt_name = NULL,
2934 .opt_action = pm_submenu, 2934 .opt_action = pm_submenu,
2935 }; 2935 };
2936 ((struct part_entry *)arg)[*i].type = d->pe_type; 2936 ((struct part_entry *)arg)[*i].type = d->pe_type;
2937 ((struct part_entry *)arg)[*i].dev_ptr = (char*)d->s->entry_first + 2937 ((struct part_entry *)arg)[*i].dev_ptr = (char*)d->s->entry_first +
2938 d->s->entry_size * ii + d->s->parent_size * d->sub_num; 2938 d->s->entry_size * ii + d->s->parent_size * d->sub_num;
2939 (*i)++; 2939 (*i)++;
2940 /* We should show submenu for current entry */ 2940 /* We should show submenu for current entry */
2941 if (d->sub != NULL) { 2941 if (d->sub != NULL) {
2942 d->sub->sub_num = ii; 2942 d->sub->sub_num = ii;
2943 pm_upddevlist_adv(m, arg, i, d->sub); 2943 pm_upddevlist_adv(m, arg, i, d->sub);
2944 } 2944 }
2945 } 2945 }
2946} 2946}
2947 2947
2948/* Update partman main menu with devices list */ 2948/* Update partman main menu with devices list */
2949static int 2949static int
2950pm_upddevlist(menudesc *m, void *arg) 2950pm_upddevlist(menudesc *m, void *arg)
2951{ 2951{
2952 int i = 0; 2952 int i = 0;
2953 size_t ii; 2953 size_t ii;
2954 struct pm_devs *pm_i; 2954 struct pm_devs *pm_i;
2955 struct disk_partitions *secondary; 2955 struct disk_partitions *secondary;
2956 const struct disk_partitioning_scheme *ps; 2956 const struct disk_partitioning_scheme *ps;
2957 struct disk_part_info info; 2957 struct disk_part_info info;
2958 2958
2959 if (arg != NULL) 2959 if (arg != NULL)
2960 pm_retvalue = m->cursel + 1; 2960 pm_retvalue = m->cursel + 1;
2961 2961
2962 pm_changed = 0; 2962 pm_changed = 0;
2963 /* Mark all devices as not found */ 2963 /* Mark all devices as not found */
2964 SLIST_FOREACH(pm_i, &pm_head, l) { 2964 SLIST_FOREACH(pm_i, &pm_head, l) {
2965 if (pm_i->parts != NULL && !pm_i->unsaved) { 2965 if (pm_i->parts != NULL && !pm_i->unsaved) {
2966 pm_i->parts->pscheme->free(pm_i->parts); 2966 pm_i->parts->pscheme->free(pm_i->parts);
2967 pm_i->parts = NULL; 2967 pm_i->parts = NULL;
2968 } 2968 }
2969 if (pm_i->found > 0) 2969 if (pm_i->found > 0)
2970 pm_i->found = 0; 2970 pm_i->found = 0;
2971 } 2971 }
2972 2972
2973 /* Detect all present devices */ 2973 /* Detect all present devices */
2974 (void)find_disks("partman", false); 2974 (void)find_disks("partman", false);
2975 if (have_lvm) 2975 if (have_lvm)
2976 pm_lvm_find(); 2976 pm_lvm_find();
2977 pm_clean(); 2977 pm_clean();
2978 2978
2979 if (m == NULL || arg == NULL) 2979 if (m == NULL || arg == NULL)
2980 return -1; 2980 return -1;
2981 2981
2982 SLIST_FOREACH(pm_i, &pm_head, l) { 2982 SLIST_FOREACH(pm_i, &pm_head, l) {
2983 memset(&m->opts[i], 0, sizeof m->opts[i]); 2983 memset(&m->opts[i], 0, sizeof m->opts[i]);
2984 m->opts[i].opt_action = pm_submenu; 2984 m->opts[i].opt_action = pm_submenu;
2985 ((struct part_entry *)arg)[i].dev_ptr = pm_i; 2985 ((struct part_entry *)arg)[i].dev_ptr = pm_i;
2986 ((struct part_entry *)arg)[i].id = NO_PART; 2986 ((struct part_entry *)arg)[i].id = NO_PART;
2987 if (pm_i->no_part) 2987 if (pm_i->no_part)
2988 ((struct part_entry *)arg)[i].type = PM_SPEC; 2988 ((struct part_entry *)arg)[i].type = PM_SPEC;
2989 else { 2989 else {
2990 ps = pm_i->parts != NULL ? pm_i->parts->pscheme : NULL; 2990 ps = pm_i->parts != NULL ? pm_i->parts->pscheme : NULL;
2991 secondary = NULL; 2991 secondary = NULL;
2992 2992
2993 ((struct part_entry *)arg)[i].type = PM_DISK; 2993 ((struct part_entry *)arg)[i].type = PM_DISK;
2994 2994
2995 for (ii = 0; pm_i->parts != NULL && 2995 for (ii = 0; pm_i->parts != NULL &&
2996 ii < pm_i->parts->num_part; ii++) { 2996 ii < pm_i->parts->num_part; ii++) {
2997 if (!ps->get_part_info( 2997 if (!ps->get_part_info(
2998 pm_i->parts, ii, &info)) 2998 pm_i->parts, ii, &info))
2999 continue; 2999 continue;
3000 if (info.flags & PTI_SEC_CONTAINER) { 3000 if (info.flags & PTI_SEC_CONTAINER) {
3001 if (secondary == NULL && 3001 if (secondary == NULL &&
3002 ps->secondary_scheme != NULL) 3002 ps->secondary_scheme != NULL)
3003 secondary = ps-> 3003 secondary = ps->
3004 secondary_partitions( 3004 secondary_partitions(
3005 pm_i->parts, 3005 pm_i->parts,
3006 info.start, false); 3006 info.start, false);
3007 continue; 3007 continue;
3008 } 3008 }
3009 if (info.flags & (PTI_WHOLE_DISK| 3009 if (info.flags & (PTI_WHOLE_DISK|
3010 PTI_PSCHEME_INTERNAL|PTI_RAW_PART)) 3010 PTI_PSCHEME_INTERNAL|PTI_RAW_PART))
3011 continue; 3011 continue;
3012 if (info.fs_type == FS_UNUSED) 3012 if (info.fs_type == FS_UNUSED)
3013 continue; 3013 continue;
3014 if (i >= MAX_ENTRIES) 3014 if (i >= MAX_ENTRIES)
3015 break; 3015 break;
3016 i++; 3016 i++;
3017 memset(&m->opts[i], 0, sizeof m->opts[i]); 3017 memset(&m->opts[i], 0, sizeof m->opts[i]);
3018 m->opts[i].opt_action = pm_submenu; 3018 m->opts[i].opt_action = pm_submenu;
3019 ((struct part_entry *)arg)[i].parts = 3019 ((struct part_entry *)arg)[i].parts =
3020 pm_i->parts; 3020 pm_i->parts;
3021 ((struct part_entry *)arg)[i].dev_ptr = pm_i; 3021 ((struct part_entry *)arg)[i].dev_ptr = pm_i;
3022 ((struct part_entry *)arg)[i].id = ii; 3022 ((struct part_entry *)arg)[i].id = ii;
3023 ((struct part_entry *)arg)[i].type = PM_PART; 3023 ((struct part_entry *)arg)[i].type = PM_PART;
3024 } 3024 }
3025 3025
3026 for (ii = 0; secondary != NULL && 3026 for (ii = 0; secondary != NULL &&
3027 ii < secondary->num_part; ii++) { 3027 ii < secondary->num_part; ii++) {
3028 if (!secondary->pscheme->get_part_info( 3028 if (!secondary->pscheme->get_part_info(
3029 secondary, ii, &info)) 3029 secondary, ii, &info))
3030 continue; 3030 continue;
3031 if (info.flags & (PTI_WHOLE_DISK| 3031 if (info.flags & (PTI_WHOLE_DISK|
3032 PTI_PSCHEME_INTERNAL|PTI_RAW_PART)) 3032 PTI_PSCHEME_INTERNAL|PTI_RAW_PART))
3033 continue; 3033 continue;
3034 if (info.fs_type == FS_UNUSED) 3034 if (info.fs_type == FS_UNUSED)
3035 continue; 3035 continue;
3036 if (i >= MAX_ENTRIES) 3036 if (i >= MAX_ENTRIES)
3037 break; 3037 break;
3038 i++; 3038 i++;
3039 memset(&m->opts[i], 0, sizeof m->opts[i]); 3039 memset(&m->opts[i], 0, sizeof m->opts[i]);
3040 m->opts[i].opt_action = pm_submenu; 3040 m->opts[i].opt_action = pm_submenu;
3041 ((struct part_entry *)arg)[i].parts = secondary; 3041 ((struct part_entry *)arg)[i].parts = secondary;
3042 ((struct part_entry *)arg)[i].dev_ptr = pm_i; 3042 ((struct part_entry *)arg)[i].dev_ptr = pm_i;
3043 ((struct part_entry *)arg)[i].id = ii; 3043 ((struct part_entry *)arg)[i].id = ii;
3044 ((struct part_entry *)arg)[i].type = PM_PART; 3044 ((struct part_entry *)arg)[i].type = PM_PART;
3045 } 3045 }
3046 } 3046 }
3047 i++; 3047 i++;
3048 } 3048 }
3049 for (ii = 0; ii <= (size_t)i; ii++) { 3049 for (ii = 0; ii <= (size_t)i; ii++) {
3050 m->opts[ii].opt_flags = OPT_EXIT; 3050 m->opts[ii].opt_flags = OPT_EXIT;
3051 } 3051 }
3052 if (have_cgd) { 3052 if (have_cgd) {
3053 pm_upddevlist_adv(m, arg, &i, 3053 pm_upddevlist_adv(m, arg, &i,
3054 &(pm_upddevlist_adv_t) {MSG_create_cgd, PM_CGD, 3054 &(pm_upddevlist_adv_t) {MSG_create_cgd, PM_CGD,
3055 &cgds_t_info, 0, NULL}); 3055 &cgds_t_info, 0, NULL});
3056 } 3056 }
3057 pm_upddevlist_adv(m, arg, &i, 3057 pm_upddevlist_adv(m, arg, &i,
3058 &(pm_upddevlist_adv_t) {MSG_create_vnd, PM_VND, 3058 &(pm_upddevlist_adv_t) {MSG_create_vnd, PM_VND,
3059 &vnds_t_info, 0, NULL}); 3059 &vnds_t_info, 0, NULL});
3060 if (have_lvm) { 3060 if (have_lvm) {
3061 pm_upddevlist_adv(m, arg, &i, 3061 pm_upddevlist_adv(m, arg, &i,
3062 &(pm_upddevlist_adv_t) {MSG_create_vg, PM_LVM, 3062 &(pm_upddevlist_adv_t) {MSG_create_vg, PM_LVM,
3063 &lvms_t_info, 0, 3063 &lvms_t_info, 0,
3064 &(pm_upddevlist_adv_t) {MSG_create_lv, PM_LVMLV, 3064 &(pm_upddevlist_adv_t) {MSG_create_lv, PM_LVMLV,
3065 &lv_t_info, 0, 3065 &lv_t_info, 0,
3066 NULL}}); 3066 NULL}});
3067 } 3067 }
3068 if (have_raid) { 3068 if (have_raid) {
3069 pm_upddevlist_adv(m, arg, &i, 3069 pm_upddevlist_adv(m, arg, &i,
3070 &(pm_upddevlist_adv_t) {MSG_create_raid, PM_RAID, &raids_t_info, 0, NULL}); 3070 &(pm_upddevlist_adv_t) {MSG_create_raid, PM_RAID, &raids_t_info, 0, NULL});
3071 } 3071 }
3072 3072
3073 m->opts[i++] = (struct menu_ent) { 3073 m->opts[i++] = (struct menu_ent) {
3074 .opt_name = MSG_updpmlist, 3074 .opt_name = MSG_updpmlist,
3075 .opt_action = pm_upddevlist, 3075 .opt_action = pm_upddevlist,
3076 }; 3076 };
3077 m->opts[i ] = (struct menu_ent) { 3077 m->opts[i ] = (struct menu_ent) {
3078 .opt_name = MSG_savepm, 3078 .opt_name = MSG_savepm,
3079 .opt_action = pm_commit, 3079 .opt_action = pm_commit,
3080 }; 3080 };
3081 3081
3082 if (pm_retvalue >= 0) 3082 if (pm_retvalue >= 0)
3083 m->cursel = pm_retvalue - 1; 3083 m->cursel = pm_retvalue - 1;
3084 return i; 3084 return i;
3085} 3085}
3086 3086
3087static void 3087static void
3088pm_menuin(menudesc *m, void *arg) 3088pm_menuin(menudesc *m, void *arg)
3089{ 3089{
3090 if (pm_cursel > m->numopts) 3090 if (pm_cursel > m->numopts)
3091 m->cursel = m->numopts; 3091 m->cursel = m->numopts;
3092 else if (pm_cursel < 0) 3092 else if (pm_cursel < 0)
3093 m->cursel = 0; 3093 m->cursel = 0;
3094 else 3094 else
3095 m->cursel = pm_cursel; 3095 m->cursel = pm_cursel;
3096} 3096}
3097 3097
3098static void 3098static void
3099pm_menuout(menudesc *m, void *arg) 3099pm_menuout(menudesc *m, void *arg)
3100{ 3100{
3101 pm_cursel = m->cursel; 3101 pm_cursel = m->cursel;
3102} 3102}
3103 3103
3104/* Main partman function */ 3104/* Main partman function */
3105int 3105int
3106partman(void) 3106partman(void)
3107{ 3107{
3108 int menu_no, menu_num_entries; 3108 int menu_no, menu_num_entries;
3109 static int firstrun = 1; 3109 static int firstrun = 1;
3110 menu_ent menu_entries[MAX_ENTRIES+6]; 3110 menu_ent menu_entries[MAX_ENTRIES+6];
3111 struct part_entry args[MAX_ENTRIES]; 3111 struct part_entry args[MAX_ENTRIES];
3112 3112
3113 if (firstrun) { 3113 if (firstrun) {
3114 check_available_binaries(); 3114 check_available_binaries();
3115 3115
3116 if (!have_raid) 3116 if (!have_raid)
3117 remove_raid_options(); 3117 remove_raid_options();
3118 else if (!(raids = calloc(MAX_RAID, sizeof(*raids)))) 3118 else if (!(raids = calloc(MAX_RAID, sizeof(*raids))))
3119 have_raid = 0; 3119 have_raid = 0;
3120 3120
3121#define remove_vnd_options() (void)0 3121#define remove_vnd_options() (void)0
3122 if (!have_vnd) 3122 if (!have_vnd)
3123 remove_vnd_options(); 3123 remove_vnd_options();
3124 else if (!(vnds = calloc(MAX_VND, sizeof(*vnds)))) 3124 else if (!(vnds = calloc(MAX_VND, sizeof(*vnds))))
3125 have_vnd = 0; 3125 have_vnd = 0;
3126 3126
3127 if (!have_cgd) 3127 if (!have_cgd)
3128 remove_cgd_options(); 3128 remove_cgd_options();
3129 else if (!(cgds = calloc(MAX_CGD, sizeof(*cgds)))) 3129 else if (!(cgds = calloc(MAX_CGD, sizeof(*cgds))))
3130 have_cgd = 0; 3130 have_cgd = 0;
3131 3131
3132 if (!have_lvm) 3132 if (!have_lvm)
3133 remove_lvm_options(); 3133 remove_lvm_options();
3134 else if (!(lvms = calloc(MAX_LVM_VG, sizeof(*lvms)))) 3134 else if (!(lvms = calloc(MAX_LVM_VG, sizeof(*lvms))))
3135 have_lvm = 0; 3135 have_lvm = 0;
3136 3136
3137 raids_t_info = (structinfo_t) { 3137 raids_t_info = (structinfo_t) {
3138 .max = MAX_RAID, 3138 .max = MAX_RAID,
3139 .entry_size = sizeof raids[0], 3139 .entry_size = sizeof raids[0],
3140 .entry_first = &raids[0], 3140 .entry_first = &raids[0],
3141 .entry_enabled = &(raids[0].enabled), 3141 .entry_enabled = &(raids[0].enabled),
3142 .entry_blocked = &(raids[0].blocked), 3142 .entry_blocked = &(raids[0].blocked),
3143 .entry_node = &(raids[0].node), 3143 .entry_node = &(raids[0].node),
3144 }; 3144 };
3145 vnds_t_info = (structinfo_t) { 3145 vnds_t_info = (structinfo_t) {
3146 .max = MAX_VND, 3146 .max = MAX_VND,
3147 .entry_size = sizeof vnds[0], 3147 .entry_size = sizeof vnds[0],
3148 .entry_first = &vnds[0], 3148 .entry_first = &vnds[0],
3149 .entry_enabled = &(vnds[0].enabled), 3149 .entry_enabled = &(vnds[0].enabled),
3150 .entry_blocked = &(vnds[0].blocked), 3150 .entry_blocked = &(vnds[0].blocked),
3151 .entry_node = &(vnds[0].node), 3151 .entry_node = &(vnds[0].node),
3152 }; 3152 };
3153 cgds_t_info = (structinfo_t) { 3153 cgds_t_info = (structinfo_t) {
3154 .max = MAX_CGD, 3154 .max = MAX_CGD,
3155 .entry_size = sizeof cgds[0], 3155 .entry_size = sizeof cgds[0],
3156 .entry_first = &cgds[0], 3156 .entry_first = &cgds[0],
3157 .entry_enabled = &(cgds[0].enabled), 3157 .entry_enabled = &(cgds[0].enabled),
3158 .entry_blocked = &(cgds[0].blocked), 3158 .entry_blocked = &(cgds[0].blocked),
3159 .entry_node = &(cgds[0].node), 3159 .entry_node = &(cgds[0].node),
3160 }; 3160 };
3161 lvms_t_info = (structinfo_t) { 3161 lvms_t_info = (structinfo_t) {
3162 .max = MAX_LVM_VG, 3162 .max = MAX_LVM_VG,
3163 .entry_size = sizeof lvms[0], 3163 .entry_size = sizeof lvms[0],
3164 .entry_first = &lvms[0], 3164 .entry_first = &lvms[0],
3165 .entry_enabled = &(lvms[0].enabled), 3165 .entry_enabled = &(lvms[0].enabled),
3166 .entry_blocked = &(lvms[0].blocked), 3166 .entry_blocked = &(lvms[0].blocked),
3167 .entry_node = NULL, 3167 .entry_node = NULL,
3168 }; 3168 };
3169 lv_t_info = (structinfo_t) { 3169 lv_t_info = (structinfo_t) {
3170 .max = MAX_LVM_LV, 3170 .max = MAX_LVM_LV,
3171 .entry_size = sizeof lvms[0].lv[0], 3171 .entry_size = sizeof lvms[0].lv[0],
3172 .entry_first = &lvms[0].lv[0], 3172 .entry_first = &lvms[0].lv[0],
3173 .entry_enabled = &(lvms[0].lv[0].size), 3173 .entry_enabled = &(lvms[0].lv[0].size),
3174 .entry_blocked = &(lvms[0].lv[0].blocked), 3174 .entry_blocked = &(lvms[0].lv[0].blocked),
3175 .parent_size = sizeof lvms[0], 3175 .parent_size = sizeof lvms[0],
3176 }; 3176 };
3177 3177
3178 pm_cursel = 0; 3178 pm_cursel = 0;
3179 pm_changed = 0; 3179 pm_changed = 0;
3180 firstrun = 0; 3180 firstrun = 0;
3181 } 3181 }
3182 3182
3183 do { 3183 do {
3184 menu_num_entries = pm_upddevlist(&(menudesc){.opts = menu_entries}, args); 3184 menu_num_entries = pm_upddevlist(&(menudesc){.opts = menu_entries}, args);
3185 menu_no = new_menu(MSG_partman_header, 3185 menu_no = new_menu(MSG_partman_header,
3186 menu_entries, menu_num_entries+1, 1, 1, 0, 75, /* Fixed width */ 3186 menu_entries, menu_num_entries+1, 1, 1, 0, 75, /* Fixed width */
3187 MC_ALWAYS_SCROLL | MC_NOBOX | MC_NOCLEAR, 3187 MC_ALWAYS_SCROLL | MC_NOBOX | MC_NOCLEAR,
3188 pm_menuin, pm_menufmt, pm_menuout, NULL, MSG_finishpm); 3188 pm_menuin, pm_menufmt, pm_menuout, NULL, MSG_finishpm);
3189 if (menu_no == -1) 3189 if (menu_no == -1)
3190 pm_retvalue = -1; 3190 pm_retvalue = -1;
3191 else { 3191 else {
3192 pm_retvalue = 0; 3192 pm_retvalue = 0;
3193 clear(); 3193 clear();
3194 refresh(); 3194 refresh();
3195 process_menu(menu_no, &args); 3195 process_menu(menu_no, &args);
3196 free_menu(menu_no); 3196 free_menu(menu_no);
3197 } 3197 }
3198 3198
3199 if (pm_retvalue == 0 && pm->parts != NULL) 3199 if (pm_retvalue == 0 && pm->parts != NULL)
3200 if (pm_needsave()) 3200 if (pm_needsave())
3201 pm_commit(NULL, NULL); 3201 pm_commit(NULL, NULL);
3202 3202
3203 } while (pm_retvalue > 0); 3203 } while (pm_retvalue > 0);
3204 3204
3205 /* retvalue <0 - error, retvalue ==0 - user quits, retvalue >0 - all ok */ 3205 /* retvalue <0 - error, retvalue ==0 - user quits, retvalue >0 - all ok */
3206 return (pm_retvalue >= 0)?0:-1; 3206 return (pm_retvalue >= 0)?0:-1;
3207} 3207}
3208 3208
3209void 3209void
3210update_wedges(const char *disk) 3210update_wedges(const char *disk)
3211{ 3211{
3212 check_available_binaries(); 3212 check_available_binaries();
3213 3213
3214 if (!have_dk) 3214 if (!have_dk)
3215 return; 3215 return;
3216 3216
3217 run_program(RUN_SILENT | RUN_ERROR_OK, 3217 run_program(RUN_SILENT | RUN_ERROR_OK,
3218 "dkctl %s makewedges", disk); 3218 "dkctl %s makewedges", disk);
3219} 3219}
3220 3220
3221bool 3221bool
3222pm_force_parts(struct pm_devs *my_pm) 3222pm_force_parts(struct pm_devs *my_pm)
3223{ 3223{
3224 if (my_pm == NULL) 3224 if (my_pm == NULL)
3225 return false; 3225 return false;
3226 if (my_pm->parts != NULL) 3226 if (my_pm->parts != NULL)
3227 return true; 3227 return true;
3228 3228
3229 const struct disk_partitioning_scheme *ps = 3229 const struct disk_partitioning_scheme *ps =
3230 select_part_scheme(my_pm, NULL, false, NULL); 3230 select_part_scheme(my_pm, NULL, false, NULL);
3231 if (ps == NULL) 3231 if (ps == NULL)
3232 return false; 3232 return false;
3233 3233
3234 struct disk_partitions *parts = 3234 struct disk_partitions *parts =
3235 (*ps->create_new_for_disk)(my_pm->diskdev, 0, 3235 (*ps->create_new_for_disk)(my_pm->diskdev, 0,
3236 my_pm->dlsize, false, NULL); 3236 my_pm->dlsize, false, NULL);
3237 if (parts == NULL) 3237 if (parts == NULL)
3238 return false; 3238 return false;
3239 3239
3240 my_pm->parts = parts; 3240 my_pm->parts = parts;
3241 if (pm->dlsize > ps->size_limit) 3241 if (pm->dlsize > ps->size_limit)
3242 pm->dlsize = ps->size_limit; 3242 pm->dlsize = ps->size_limit;
3243 3243
3244 return true; 3244 return true;
3245} 3245}
3246 3246
3247void 3247void
3248pm_edit_partitions(struct part_entry *pe) 3248pm_edit_partitions(struct part_entry *pe)
3249{ 3249{
3250 struct pm_devs *my_pm = pm_from_pe(pe); 3250 struct pm_devs *my_pm = pm_from_pe(pe);
3251 struct partition_usage_set pset = { 0 }; 3251 struct partition_usage_set pset = { 0 };
3252 struct disk_partitions *parts, *np; 3252 struct disk_partitions *parts, *np;
3253 3253
3254 if (!my_pm) 3254 if (!my_pm)
3255 return; 3255 return;
3256 3256
3257 if (!pm_force_parts(my_pm)) 3257 if (!pm_force_parts(my_pm))
3258 return; 3258 return;
3259 parts = my_pm->parts; 3259 parts = my_pm->parts;
3260 3260
3261 clear(); 3261 clear();
3262 refresh(); 3262 refresh();
3263 3263
3264 if (my_pm->parts->pscheme->secondary_scheme != NULL) { 3264 if (my_pm->parts->pscheme->secondary_scheme != NULL) {
3265 if (!edit_outer_parts(my_pm->parts)) 3265 if (!edit_outer_parts(my_pm->parts))
3266 goto done; 3266 goto done;
3267 np = get_inner_parts(parts); 3267 np = get_inner_parts(parts);
3268 if (np != NULL) 3268 if (np != NULL)
3269 parts = np; 3269 parts = np;
3270 } 3270 }
3271 3271
3272 if (parts != NULL) { 3272 if (parts != NULL) {
3273 usage_set_from_parts(&pset, parts); 3273 usage_set_from_parts(&pset, parts);
3274 edit_and_check_label(my_pm, &pset, false); 3274 edit_and_check_label(my_pm, &pset, false);
3275 free_usage_set(&pset); 3275 free_usage_set(&pset);
3276 } 3276 }
3277 3277
3278done: 3278done:
3279 pm_partusage(my_pm, -1, -1); 3279 pm_partusage(my_pm, -1, -1);
3280 my_pm->unsaved = true; 3280 my_pm->unsaved = true;
3281 pm_retvalue = 1; 3281 pm_retvalue = 1;
3282} 3282}
3283 3283
3284part_id 3284part_id
3285pm_whole_disk(struct part_entry *pe, int t) 3285pm_whole_disk(struct part_entry *pe, int t)
3286{ 3286{
3287 struct pm_devs *my_pm = pm_from_pe(pe); 3287 struct pm_devs *my_pm = pm_from_pe(pe);
3288 struct disk_partitions *parts, *outer; 3288 struct disk_partitions *parts, *outer;
3289 struct disk_part_info info, oinfo; 3289 struct disk_part_info info, oinfo;
3290 struct disk_part_free_space space; 3290 struct disk_part_free_space space;
3291 daddr_t align; 3291 daddr_t align;
3292 int fst; 3292 int fst;
3293 struct partition_usage_set pset = { 0 }; 3293 struct partition_usage_set pset = { 0 };
3294 part_id new_part, id; 3294 part_id new_part, id;
3295 size_t i, cnt; 3295 size_t i, cnt;
3296 3296
3297 if (!my_pm) 3297 if (!my_pm)
3298 return NO_PART; 3298 return NO_PART;
3299 3299
3300 if (!pm_force_parts(my_pm)) 3300 if (!pm_force_parts(my_pm))
3301 return NO_PART; 3301 return NO_PART;
3302 3302
3303 parts = my_pm->parts; 3303 parts = my_pm->parts;
3304 parts->pscheme->delete_all_partitions(parts); 3304 parts->pscheme->delete_all_partitions(parts);
3305 if (parts->pscheme->secondary_scheme != NULL) { 3305 if (parts->pscheme->secondary_scheme != NULL) {
3306 outer = parts; 3306 outer = parts;
3307 parts = parts->pscheme->secondary_partitions(outer, 3307 parts = parts->pscheme->secondary_partitions(outer,
3308 0, true); 3308 0, true);
3309 if (parts == NULL) { 3309 if (parts == NULL) {
3310 parts = outer; 3310 parts = outer;
3311 } else { 3311 } else {
3312 if (outer->pscheme->write_to_disk(outer)) 3312 if (outer->pscheme->write_to_disk(outer))
3313 my_pm->parts = parts; 3313 my_pm->parts = parts;
3314 } 3314 }
3315 } 3315 }
3316 3316
3317 align = parts->pscheme->get_part_alignment(parts); 3317 align = parts->pscheme->get_part_alignment(parts);
3318 3318
3319 memset(&info, 0, sizeof info); 3319 memset(&info, 0, sizeof info);
3320 switch (t) { 3320 switch (t) {
3321 case SY_NEWRAID: 3321 case SY_NEWRAID:
3322 fst = FS_RAID; 3322 fst = FS_RAID;
3323 break; 3323 break;
3324 case SY_NEWLVM: 3324 case SY_NEWLVM:
3325 fst = FS_BSDFFS; 3325 fst = FS_BSDFFS;
3326 break; 3326 break;
3327 case SY_NEWCGD: 3327 case SY_NEWCGD:
3328 fst = FS_CGD; 3328 fst = FS_CGD;
3329 break; 3329 break;
3330 default: 3330 default:
3331 assert(false); 3331 assert(false);
3332 return NO_PART; 3332 return NO_PART;
3333 } 3333 }
3334 info.nat_type = parts->pscheme->get_fs_part_type(PT_root, fst, 0); 3334 info.nat_type = parts->pscheme->get_fs_part_type(PT_root, fst, 0);
3335 if (info.nat_type != NULL && parts->pscheme->get_default_fstype != NULL) 3335 if (info.nat_type != NULL && parts->pscheme->get_default_fstype != NULL)
3336 parts->pscheme->get_default_fstype(info.nat_type, 3336 parts->pscheme->get_default_fstype(info.nat_type,
3337 &info.fs_type, &info.fs_sub_type); 3337 &info.fs_type, &info.fs_sub_type);
3338 if (parts->pscheme->get_free_spaces(parts, &space, 1, 3338 if (parts->pscheme->get_free_spaces(parts, &space, 1,
3339 5*align, align, -1, -1) != 1) 3339 5*align, align, -1, -1) != 1)
3340 return NO_PART; 3340 return NO_PART;
3341 info.start = space.start; 3341 info.start = space.start;
3342 info.size = space.size; 3342 info.size = space.size;
3343 new_part = parts->pscheme->add_partition(parts, &info, NULL); 3343 new_part = parts->pscheme->add_partition(parts, &info, NULL);
3344 if (new_part == NO_PART) 3344 if (new_part == NO_PART)
3345 return NO_PART; 3345 return NO_PART;
3346 3346
3347 parts->pscheme->get_part_info(parts, new_part, &oinfo); 3347 parts->pscheme->get_part_info(parts, new_part, &oinfo);
3348 3348
3349 clear(); 3349 clear();
3350 refresh(); 3350 refresh();
3351 3351
3352 usage_set_from_parts(&pset, parts); 3352 usage_set_from_parts(&pset, parts);
3353 edit_and_check_label(my_pm, &pset, false); 3353 edit_and_check_label(my_pm, &pset, false);
3354 free_usage_set(&pset); 3354 free_usage_set(&pset);
3355 3355
3356 /* 3356 /*
3357 * Try to match our new partition after user edit 3357 * Try to match our new partition after user edit
3358 */ 3358 */
3359 new_part = NO_PART; 3359 new_part = NO_PART;
3360 for (cnt = i = 0; i < parts->num_part; i++) { 3360 for (cnt = i = 0; i < parts->num_part; i++) {
3361 if (!parts->pscheme->get_part_info(parts,i, &info)) 3361 if (!parts->pscheme->get_part_info(parts,i, &info))
3362 continue; 3362 continue;
3363 if (info.flags & (PTI_SEC_CONTAINER|PTI_WHOLE_DISK| 3363 if (info.flags & (PTI_SEC_CONTAINER|PTI_WHOLE_DISK|
3364 PTI_PSCHEME_INTERNAL|PTI_RAW_PART)) 3364 PTI_PSCHEME_INTERNAL|PTI_RAW_PART))
3365 continue; 3365 continue;
3366 if (info.nat_type != oinfo.nat_type) 3366 if (info.nat_type != oinfo.nat_type)
3367 continue; 3367 continue;
3368 if (new_part == NO_PART) 3368 if (new_part == NO_PART)
3369 new_part = i; 3369 new_part = i;
3370 cnt++; 3370 cnt++;
3371 } 3371 }
3372 if (cnt > 1) { 3372 if (cnt > 1) {
3373 /* multiple matches, retry matching with start */ 3373 /* multiple matches, retry matching with start */
3374 id = NO_PART; 3374 id = NO_PART;
3375 for (cnt = i = 0; i < parts->num_part; i++) { 3375 for (cnt = i = 0; i < parts->num_part; i++) {
3376 if (!parts->pscheme->get_part_info(parts, i, &info)) 3376 if (!parts->pscheme->get_part_info(parts, i, &info))
3377 continue; 3377 continue;
3378 if (info.flags & (PTI_SEC_CONTAINER|PTI_WHOLE_DISK| 3378 if (info.flags & (PTI_SEC_CONTAINER|PTI_WHOLE_DISK|
3379 PTI_PSCHEME_INTERNAL|PTI_RAW_PART)) 3379 PTI_PSCHEME_INTERNAL|PTI_RAW_PART))
3380 continue; 3380 continue;
3381 if (info.nat_type != oinfo.nat_type) 3381 if (info.nat_type != oinfo.nat_type)
3382 continue; 3382 continue;
3383 if (info.start != oinfo.start) 3383 if (info.start != oinfo.start)
3384 continue; 3384 continue;
3385 if (id == NO_PART) 3385 if (id == NO_PART)
3386 id = i; 3386 id = i;
3387 cnt++; 3387 cnt++;
3388 } 3388 }
3389 if (id != NO_PART) 3389 if (id != NO_PART)
3390 new_part = id; 3390 new_part = id;
3391 } 3391 }
3392 3392
3393 clear(); 3393 clear();
3394 refresh(); 3394 refresh();
3395 3395
3396 pm_partusage(my_pm, -1, -1); 3396 pm_partusage(my_pm, -1, -1);
3397 my_pm->unsaved = true; 3397 my_pm->unsaved = true;
3398 pm_retvalue = 1; 3398 pm_retvalue = 1;
3399 3399
3400 return new_part; 3400 return new_part;
3401} 3401}
3402 3402
3403struct pm_devs * 3403struct pm_devs *
3404pm_from_pe(struct part_entry *pe) 3404pm_from_pe(struct part_entry *pe)
3405{ 3405{
3406 switch (pe->type) { 3406 switch (pe->type) {
3407 case PM_DISK: 3407 case PM_DISK:
3408 return pe->dev_ptr; 3408 return pe->dev_ptr;
3409 default: 3409 default:
3410 assert(false); 3410 assert(false);
3411 } 3411 }
3412 return NULL; 3412 return NULL;
3413} 3413}