Bug Summary

File:src/sbin/disklabel/editor.c
Warning:line 2503, column 37
Division by zero

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name editor.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sbin/disklabel/obj -resource-dir /usr/local/lib/clang/13.0.0 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/sbin/disklabel/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/sbin/disklabel/editor.c
1/* $OpenBSD: editor.c,v 1.370 2021/12/19 19:26:18 krw Exp $ */
2
3/*
4 * Copyright (c) 1997-2000 Todd C. Miller <millert@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <sys/param.h> /* MAXBSIZE DEV_BSIZE */
20#include <sys/types.h>
21#include <sys/signal.h>
22#include <sys/stat.h>
23#include <sys/ioctl.h>
24#include <sys/dkio.h>
25#include <sys/sysctl.h>
26#define DKTYPENAMES
27#include <sys/disklabel.h>
28
29#include <ufs/ffs/fs.h>
30
31#include <ctype.h>
32#include <err.h>
33#include <errno(*__errno()).h>
34#include <string.h>
35#include <libgen.h>
36#include <stdint.h>
37#include <stdio.h>
38#include <stdlib.h>
39#include <unistd.h>
40#include <limits.h>
41
42#include "extern.h"
43#include "pathnames.h"
44
45#define MAXIMUM(a, b)(((a) > (b)) ? (a) : (b)) (((a) > (b)) ? (a) : (b))
46
47/* flags for getuint64() */
48#define DO_CONVERSIONS0x00000001 0x00000001
49#define DO_ROUNDING0x00000002 0x00000002
50
51/* flags for alignpartition() */
52#define ROUND_OFFSET_UP0x00000001 0x00000001
53#define ROUND_OFFSET_DOWN0x00000002 0x00000002
54#define ROUND_SIZE_UP0x00000004 0x00000004
55#define ROUND_SIZE_DOWN0x00000008 0x00000008
56#define ROUND_SIZE_OVERLAP0x00000010 0x00000010
57
58/* Special return values for getnumber and getuint64() */
59#define CMD_ABORTED((9223372036854775807LL*2ULL+1ULL) - 1) (ULLONG_MAX(9223372036854775807LL*2ULL+1ULL) - 1)
60#define CMD_BADVALUE((9223372036854775807LL*2ULL+1ULL)) (ULLONG_MAX(9223372036854775807LL*2ULL+1ULL))
61
62/* structure to describe a portion of a disk */
63struct diskchunk {
64 u_int64_t start;
65 u_int64_t stop;
66};
67
68/* used when sorting mountpoints in mpsave() */
69struct mountinfo {
70 char *mountpoint;
71 int partno;
72};
73
74/* used when allocating all space according to recommendations */
75
76struct space_allocation {
77 u_int64_t minsz; /* starts as blocks, xlated to sectors. */
78 u_int64_t maxsz; /* starts as blocks, xlated to sectors. */
79 int rate; /* % of extra space to use */
80 char *mp;
81};
82
83/*
84 * NOTE! Changing partition sizes in the space_allocation tables
85 * requires corresponding updates to the *.ok files in
86 * /usr/src/regress/sbin/disklabel.
87 */
88
89/* entries for swap and var are changed by editor_allocspace() */
90struct space_allocation alloc_big[] = {
91 { MEG(150)((150) * 1024LL * (1024 / (1 << 9))), GIG(1)(((1) * 1024LL * (1024 / (1 << 9))) * 1024LL), 5, "/" },
92 { MEG(80)((80) * 1024LL * (1024 / (1 << 9))), MEG(256)((256) * 1024LL * (1024 / (1 << 9))), 10, "swap" },
93 { MEG(120)((120) * 1024LL * (1024 / (1 << 9))), GIG(4)(((4) * 1024LL * (1024 / (1 << 9))) * 1024LL), 8, "/tmp" },
94 { MEG(80)((80) * 1024LL * (1024 / (1 << 9))), GIG(4)(((4) * 1024LL * (1024 / (1 << 9))) * 1024LL), 13, "/var" },
95 { MEG(1500)((1500) * 1024LL * (1024 / (1 << 9))), GIG(6)(((6) * 1024LL * (1024 / (1 << 9))) * 1024LL), 10, "/usr" },
96 { MEG(384)((384) * 1024LL * (1024 / (1 << 9))), GIG(1)(((1) * 1024LL * (1024 / (1 << 9))) * 1024LL), 3, "/usr/X11R6" },
97 { GIG(1)(((1) * 1024LL * (1024 / (1 << 9))) * 1024LL), GIG(20)(((20) * 1024LL * (1024 / (1 << 9))) * 1024LL), 15, "/usr/local" },
98 { MEG(1500)((1500) * 1024LL * (1024 / (1 << 9))), GIG(3)(((3) * 1024LL * (1024 / (1 << 9))) * 1024LL), 2, "/usr/src" },
99 { GIG(5)(((5) * 1024LL * (1024 / (1 << 9))) * 1024LL), GIG(6)(((6) * 1024LL * (1024 / (1 << 9))) * 1024LL), 4, "/usr/obj" },
100 { GIG(1)(((1) * 1024LL * (1024 / (1 << 9))) * 1024LL), GIG(300)(((300) * 1024LL * (1024 / (1 << 9))) * 1024LL), 30, "/home" }
101 /* Anything beyond this leave for the user to decide */
102};
103
104struct space_allocation alloc_medium[] = {
105 { MEG(800)((800) * 1024LL * (1024 / (1 << 9))), GIG(2)(((2) * 1024LL * (1024 / (1 << 9))) * 1024LL), 5, "/" },
106 { MEG(80)((80) * 1024LL * (1024 / (1 << 9))), MEG(256)((256) * 1024LL * (1024 / (1 << 9))), 10, "swap" },
107 { MEG(1300)((1300) * 1024LL * (1024 / (1 << 9))), GIG(3)(((3) * 1024LL * (1024 / (1 << 9))) * 1024LL), 78, "/usr" },
108 { MEG(256)((256) * 1024LL * (1024 / (1 << 9))), GIG(2)(((2) * 1024LL * (1024 / (1 << 9))) * 1024LL), 7, "/home" }
109};
110
111struct space_allocation alloc_small[] = {
112 { MEG(700)((700) * 1024LL * (1024 / (1 << 9))), GIG(4)(((4) * 1024LL * (1024 / (1 << 9))) * 1024LL), 95, "/" },
113 { MEG(1)((1) * 1024LL * (1024 / (1 << 9))), MEG(256)((256) * 1024LL * (1024 / (1 << 9))), 5, "swap" }
114};
115
116struct space_allocation alloc_stupid[] = {
117 { MEG(1)((1) * 1024LL * (1024 / (1 << 9))), MEG(2048)((2048) * 1024LL * (1024 / (1 << 9))), 100, "/" }
118};
119
120#ifndef nitems
121#define nitems(_a)(sizeof((_a)) / sizeof((_a)[0])) (sizeof((_a)) / sizeof((_a)[0]))
122#endif
123
124struct alloc_table {
125 struct space_allocation *table;
126 int sz;
127};
128
129struct alloc_table alloc_table_default[] = {
130 { alloc_big, nitems(alloc_big)(sizeof((alloc_big)) / sizeof((alloc_big)[0])) },
131 { alloc_medium, nitems(alloc_medium)(sizeof((alloc_medium)) / sizeof((alloc_medium)[0])) },
132 { alloc_small, nitems(alloc_small)(sizeof((alloc_small)) / sizeof((alloc_small)[0])) },
133 { alloc_stupid, nitems(alloc_stupid)(sizeof((alloc_stupid)) / sizeof((alloc_stupid)[0])) }
134};
135struct alloc_table *alloc_table = alloc_table_default;
136int alloc_table_nitems = 4;
137
138void edit_parms(struct disklabel *);
139void editor_resize(struct disklabel *, char *);
140void editor_add(struct disklabel *, char *);
141void editor_change(struct disklabel *, char *);
142u_int64_t editor_countfree(struct disklabel *);
143void editor_delete(struct disklabel *, char *);
144void editor_help(void);
145void editor_modify(struct disklabel *, char *);
146void editor_name(struct disklabel *, char *);
147char *getstring(const char *, const char *, const char *);
148u_int64_t getuint64(struct disklabel *, char *, char *, u_int64_t,
149 u_int64_t, int *);
150u_int64_t getnumber(char *, char *, u_int32_t, u_int32_t);
151int has_overlap(struct disklabel *);
152int partition_cmp(const void *, const void *);
153struct partition **sort_partitions(struct disklabel *);
154void getdisktype(struct disklabel *, char *, char *);
155void find_bounds(struct disklabel *);
156void set_bounds(struct disklabel *);
157void set_duid(struct disklabel *);
158struct diskchunk *free_chunks(struct disklabel *);
159int micmp(const void *, const void *);
160int mpequal(char **, char **);
161int get_bsize(struct disklabel *, int);
162int get_fsize(struct disklabel *, int);
163int get_cpg(struct disklabel *, int);
164int get_fstype(struct disklabel *, int);
165int get_mp(struct disklabel *, int);
166int get_offset(struct disklabel *, int);
167int get_size(struct disklabel *, int);
168void get_geometry(int, struct disklabel **);
169void set_geometry(struct disklabel *, struct disklabel *, struct disklabel *,
170 char *);
171void zero_partitions(struct disklabel *);
172u_int64_t max_partition_size(struct disklabel *, int);
173void display_edit(struct disklabel *, char);
174void psize(u_int64_t sz, char unit, struct disklabel *lp);
175char *get_token(char **);
176int apply_unit(double, u_char, u_int64_t *);
177int parse_sizespec(const char *, double *, char **);
178int parse_sizerange(char *, u_int64_t *, u_int64_t *);
179int parse_pct(char *, int *);
180int alignpartition(struct disklabel *, int, u_int64_t, u_int64_t, int);
181
182static u_int64_t starting_sector;
183static u_int64_t ending_sector;
184static int expert;
185static int overlap;
186
187/*
188 * Simple partition editor.
189 */
190int
191editor(int f)
192{
193 struct disklabel origlabel, lastlabel, tmplabel, newlab = lab;
194 struct disklabel *disk_geop = NULL((void *)0);
195 struct partition *pp;
196 FILE *fp;
197 char buf[BUFSIZ1024], *cmd, *arg;
198 char **omountpoints = NULL((void *)0);
199 char **origmountpoints = NULL((void *)0), **tmpmountpoints = NULL((void *)0);
200 int i, error = 0;
201
202 /* Alloc and init mount point info */
203 if (!(omountpoints = calloc(MAXPARTITIONS16, sizeof(char *))) ||
1
Assuming 'omountpoints' is non-null
4
Taking false branch
204 !(origmountpoints = calloc(MAXPARTITIONS16, sizeof(char *))) ||
2
Assuming 'origmountpoints' is non-null
205 !(tmpmountpoints = calloc(MAXPARTITIONS16, sizeof(char *))))
3
Assuming 'tmpmountpoints' is non-null
206 errx(4, "out of memory");
207
208 /* Don't allow disk type of "unknown" */
209 getdisktype(&newlab, "You need to specify a type for this disk.",
210 specname);
211
212 /* Get the on-disk geometries if possible */
213 get_geometry(f, &disk_geop);
214
215 /* How big is the OpenBSD portion of the disk? */
216 find_bounds(&newlab);
217
218 /* Make sure there is no partition overlap. */
219 if (has_overlap(&newlab))
5
Taking false branch
220 errx(1, "can't run when there is partition overlap.");
221
222 /* If we don't have a 'c' partition, create one. */
223 pp = &newlab.d_partitions[RAW_PART2];
224 if (newlab.d_npartitions
5.1
Field 'd_npartitions' is < 3
< 3 || DL_GETPSIZE(pp)(((u_int64_t)(pp)->p_sizeh << 32) + (pp)->p_size) == 0) {
225 puts("No 'c' partition found, adding one that spans the disk.");
226 if (newlab.d_npartitions
5.2
Field 'd_npartitions' is < 3
< 3)
6
Taking true branch
227 newlab.d_npartitions = 3;
228 DL_SETPOFFSET(pp, 0)do { u_int64_t __x = (0); (pp)->p_offseth = __x >> 32
; (pp)->p_offset = __x; } while (0)
;
7
Loop condition is false. Exiting loop
229 DL_SETPSIZE(pp, DL_GETDSIZE(&newlab))do { u_int64_t __x = ((((u_int64_t)(&newlab)->d_secperunith
<< 32) + (&newlab)->d_secperunit)); (pp)->p_sizeh
= __x >> 32; (pp)->p_size = __x; } while (0)
;
8
Loop condition is false. Exiting loop
230 pp->p_fstype = FS_UNUSED0;
231 pp->p_fragblock = pp->p_cpg = 0;
232 }
233
234#ifdef SUN_CYLCHECK
235 if ((newlab.d_flags & D_VENDOR0x08) && !quiet) {
236 puts("This platform requires that partition offsets/sizes "
237 "be on cylinder boundaries.\n"
238 "Partition offsets/sizes will be rounded to the "
239 "nearest cylinder automatically.");
240 }
241#endif
242
243 /* Set d_bbsize and d_sbsize as necessary */
244 if (newlab.d_bbsize == 0)
9
Assuming field 'd_bbsize' is not equal to 0
10
Taking false branch
245 newlab.d_bbsize = BBSIZE8192;
246 if (newlab.d_sbsize == 0)
11
Assuming field 'd_sbsize' is not equal to 0
12
Taking false branch
247 newlab.d_sbsize = SBSIZE8192;
248
249 /* Save the (U|u)ndo labels and mountpoints. */
250 mpcopy(origmountpoints, mountpoints);
251 origlabel = newlab;
252 lastlabel = newlab;
253
254 puts("Label editor (enter '?' for help at any prompt)");
255 for (;;) {
13
Loop condition is true. Entering loop body
256 fprintf(stdout(&__sF[1]), "%s%s%c ", dkname,
257 (memcmp(&lab, &newlab, sizeof(newlab)) == 0) ? "" : "*",
14
Assuming the condition is false
15
'?' condition is false
258 (expert == 0) ? '>' : '#');
16
Assuming 'expert' is not equal to 0
17
'?' condition is false
259 if (fgets(buf, sizeof(buf), stdin(&__sF[0])) == NULL((void *)0)) {
18
Assuming the condition is false
19
Taking false branch
260 putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
261 buf[0] = 'q';
262 buf[1] = '\0';
263 }
264 if ((cmd = strtok(buf, " \t\r\n")) == NULL((void *)0))
20
Assuming the condition is false
21
Taking false branch
265 continue;
266 arg = strtok(NULL((void *)0), " \t\r\n");
267
268 if ((*cmd != 'u') && (*cmd != 'U')) {
22
Assuming the condition is true
23
Assuming the condition is true
24
Taking true branch
269 /*
270 * Save undo info in case the command tries to make
271 * changes but decides not to.
272 */
273 tmplabel = lastlabel;
274 lastlabel = newlab;
275 mpcopy(tmpmountpoints, omountpoints);
276 mpcopy(omountpoints, mountpoints);
277 }
278
279 switch (*cmd) {
25
Control jumps to 'case 82:' at line 418
280 case '?':
281 case 'h':
282 editor_help();
283 break;
284
285 case 'A':
286 if (ioctl(f, DIOCGPDINFO((unsigned long)0x40000000 | ((sizeof(struct disklabel) &
0x1fff) << 16) | ((('d')) << 8) | ((114)))
, &newlab) == -1) {
287 warn("DIOCGPDINFO");
288 newlab = lastlabel;
289 } else {
290 int oquiet = quiet, oexpert = expert;
291 aflag = 1;
292 quiet = expert = 0;
293 editor_allocspace(&newlab);
294 quiet = oquiet;
295 expert = oexpert;
296 }
297 break;
298 case 'a':
299 editor_add(&newlab, arg);
300 break;
301
302 case 'b':
303 set_bounds(&newlab);
304 break;
305
306 case 'c':
307 editor_change(&newlab, arg);
308 break;
309
310 case 'D':
311 if (ioctl(f, DIOCGPDINFO((unsigned long)0x40000000 | ((sizeof(struct disklabel) &
0x1fff) << 16) | ((('d')) << 8) | ((114)))
, &newlab) == -1)
312 warn("DIOCGPDINFO");
313 else {
314 dflag = 1;
315 for (i = 0; i < MAXPARTITIONS16; i++) {
316 free(mountpoints[i]);
317 mountpoints[i] = NULL((void *)0);
318 }
319 }
320 break;
321
322 case 'd':
323 editor_delete(&newlab, arg);
324 break;
325
326 case 'e':
327 edit_parms(&newlab);
328 break;
329
330 case 'g':
331 set_geometry(&newlab, disk_geop, &lab, arg);
332 break;
333
334 case 'i':
335 set_duid(&newlab);
336 break;
337
338 case 'm':
339 editor_modify(&newlab, arg);
340 break;
341
342 case 'n':
343 if (!fstabfile) {
344 fputs("This option is not valid when run "
345 "without the -F or -f flags.\n", stderr(&__sF[2]));
346 break;
347 }
348 editor_name(&newlab, arg);
349 break;
350
351 case 'p':
352 display_edit(&newlab, arg ? *arg : 0);
353 break;
354
355 case 'l':
356 display(stdout(&__sF[1]), &newlab, arg ? *arg : 0, 0);
357 break;
358
359 case 'M': {
360 sig_t opipe = signal(SIGPIPE13, SIG_IGN(void (*)(int))1);
361 char *pager, *comm = NULL((void *)0);
362 extern const u_char manpage[];
363 extern const int manpage_sz;
364
365 if ((pager = getenv("PAGER")) == NULL((void *)0) || *pager == '\0')
366 pager = _PATH_LESS"/usr/bin/less";
367
368 if (asprintf(&comm, "gunzip -qc|%s", pager) != -1 &&
369 (fp = popen(comm, "w")) != NULL((void *)0)) {
370 (void) fwrite(manpage, manpage_sz, 1, fp);
371 pclose(fp);
372 } else
373 warn("unable to execute %s", pager);
374
375 free(comm);
376 (void)signal(SIGPIPE13, opipe);
377 break;
378 }
379
380 case 'q':
381 if (donothing) {
382 puts("In no change mode, not writing label.");
383 goto done;
384 }
385
386 /*
387 * If we haven't changed the original label, and it
388 * wasn't a default label or an auto-allocated label,
389 * there is no need to do anything before exiting. Note
390 * that 'w' will reset dflag and aflag to allow 'q' to
391 * exit without further questions.
392 */
393 if (!dflag && !aflag &&
394 memcmp(&lab, &newlab, sizeof(newlab)) == 0) {
395 puts("No label changes.");
396 /* Save mountpoint info. */
397 mpsave(&newlab);
398 goto done;
399 }
400 do {
401 arg = getstring("Write new label?",
402 "Write the modified label to disk?",
403 "y");
404 } while (arg && tolower((unsigned char)*arg) != 'y' &&
405 tolower((unsigned char)*arg) != 'n');
406 if (arg && tolower((unsigned char)*arg) == 'y') {
407 if (writelabel(f, &newlab) == 0) {
408 newlab = lab; /* lab now has UID info */
409 goto done;
410 }
411 warnx("unable to write label");
412 }
413 error = 1;
414 goto done;
415 /* NOTREACHED */
416 break;
417
418 case 'R':
419 if (aflag && !overlap)
26
Assuming 'aflag' is not equal to 0
27
Assuming 'overlap' is 0
28
Taking true branch
420 editor_resize(&newlab, arg);
29
Calling 'editor_resize'
421 else
422 fputs("Resize only implemented for auto "
423 "allocated labels\n", stderr(&__sF[2]));
424 break;
425
426 case 'r': {
427 struct diskchunk *chunks;
428 int i;
429 /* Display free space. */
430 chunks = free_chunks(&newlab);
431 for (i = 0; chunks[i].start != 0 || chunks[i].stop != 0;
432 i++)
433 fprintf(stderr(&__sF[2]), "Free sectors: %16llu - %16llu "
434 "(%16llu)\n",
435 chunks[i].start, chunks[i].stop - 1,
436 chunks[i].stop - chunks[i].start);
437 fprintf(stderr(&__sF[2]), "Total free sectors: %llu.\n",
438 editor_countfree(&newlab));
439 break;
440 }
441
442 case 's':
443 if (arg == NULL((void *)0)) {
444 arg = getstring("Filename",
445 "Name of the file to save label into.",
446 NULL((void *)0));
447 if (arg == NULL((void *)0) || *arg == '\0')
448 break;
449 }
450 if ((fp = fopen(arg, "w")) == NULL((void *)0)) {
451 warn("cannot open %s", arg);
452 } else {
453 display(fp, &newlab, 0, 1);
454 (void)fclose(fp);
455 }
456 break;
457
458 case 'U':
459 /*
460 * If we allow 'U' repeatedly, information would be
461 * lost. This way multiple 'U's followed by 'u' will
462 * undo the 'U's.
463 */
464 if (memcmp(&newlab, &origlabel, sizeof(newlab)) ||
465 !mpequal(mountpoints, origmountpoints)) {
466 tmplabel = newlab;
467 newlab = origlabel;
468 lastlabel = tmplabel;
469 mpcopy(tmpmountpoints, mountpoints);
470 mpcopy(mountpoints, origmountpoints);
471 mpcopy(omountpoints, tmpmountpoints);
472 }
473 puts("Original label and mount points restored.");
474 break;
475
476 case 'u':
477 tmplabel = newlab;
478 newlab = lastlabel;
479 lastlabel = tmplabel;
480 mpcopy(tmpmountpoints, mountpoints);
481 mpcopy(mountpoints, omountpoints);
482 mpcopy(omountpoints, tmpmountpoints);
483 puts("Last change undone.");
484 break;
485
486 case 'w':
487 if (donothing) {
488 puts("In no change mode, not writing label.");
489 break;
490 }
491
492 /* Write label to disk. */
493 if (writelabel(f, &newlab) != 0)
494 warnx("unable to write label");
495 else {
496 dflag = aflag = 0;
497 newlab = lab; /* lab now has UID info */
498 }
499 break;
500
501 case 'X':
502 expert = !expert;
503 printf("%s expert mode\n", expert ? "Entering" :
504 "Exiting");
505 break;
506
507 case 'x':
508 goto done;
509 break;
510
511 case 'z':
512 zero_partitions(&newlab);
513 break;
514
515 case '\n':
516 break;
517
518 default:
519 printf("Unknown option: %c ('?' for help)\n", *cmd);
520 break;
521 }
522
523 /*
524 * If no changes were made to label or mountpoints, then
525 * restore undo info.
526 */
527 if (memcmp(&newlab, &lastlabel, sizeof(newlab)) == 0 &&
528 (mpequal(mountpoints, omountpoints))) {
529 lastlabel = tmplabel;
530 mpcopy(omountpoints, tmpmountpoints);
531 }
532 }
533done:
534 mpfree(omountpoints);
535 mpfree(origmountpoints);
536 mpfree(tmpmountpoints);
537 free(disk_geop);
538 return (error);
539}
540
541/*
542 * Allocate all disk space according to standard recommendations for a
543 * root disk.
544 */
545int
546editor_allocspace(struct disklabel *lp_org)
547{
548 struct disklabel *lp, label;
549 struct space_allocation *alloc;
550 struct space_allocation *ap;
551 struct partition *pp;
552 struct diskchunk *chunks;
553 u_int64_t chunkstart, chunkstop, chunksize;
554 u_int64_t cylsecs, secs, xtrasecs;
555 char **partmp;
556 int i, j, lastalloc, index, partno, freeparts;
557 extern int64_t physmem;
558
559 /* How big is the OpenBSD portion of the disk? */
560 find_bounds(lp_org);
561
562 overlap = 0;
563 freeparts = 0;
564 for (i = 0; i < MAXPARTITIONS16; i++) {
565 u_int64_t psz, pstart, pend;
566
567 pp = &lp_org->d_partitions[i];
568 psz = DL_GETPSIZE(pp)(((u_int64_t)(pp)->p_sizeh << 32) + (pp)->p_size);
569 if (psz == 0)
570 freeparts++;
571 pstart = DL_GETPOFFSET(pp)(((u_int64_t)(pp)->p_offseth << 32) + (pp)->p_offset
)
;
572 pend = pstart + psz;
573 if (i != RAW_PART2 && psz != 0 &&
574 ((pstart >= starting_sector && pstart < ending_sector) ||
575 (pend > starting_sector && pend <= ending_sector))) {
576 overlap = 1;
577 break;
578 }
579 }
580
581 cylsecs = lp_org->d_secpercyl;
582 alloc = NULL((void *)0);
583 index = -1;
584again:
585 free(alloc);
586 alloc = NULL((void *)0);
587 index++;
588 if (index >= alloc_table_nitems)
589 return 1;
590 lp = &label;
591 for (i=0; i<MAXPARTITIONS16; i++) {
592 free(mountpoints[i]);
593 mountpoints[i] = NULL((void *)0);
594 }
595 memcpy(lp, lp_org, sizeof(struct disklabel));
596 lp->d_npartitions = MAXPARTITIONS16;
597 lastalloc = alloc_table[index].sz;
598 if (lastalloc > freeparts)
599 goto again;
600 alloc = reallocarray(NULL((void *)0), lastalloc, sizeof(struct space_allocation));
601 if (alloc == NULL((void *)0))
602 errx(4, "out of memory");
603 memcpy(alloc, alloc_table[index].table,
604 lastalloc * sizeof(struct space_allocation));
605
606 /* bump max swap based on phys mem, little physmem gets 2x swap */
607 if (index == 0 && alloc_table == alloc_table_default) {
608 if (physmem && physmem / DEV_BSIZE(1 << 9) < MEG(256)((256) * 1024LL * (1024 / (1 << 9))))
609 alloc[1].minsz = alloc[1].maxsz = 2 * (physmem /
610 DEV_BSIZE(1 << 9));
611 else
612 alloc[1].maxsz += (physmem / DEV_BSIZE(1 << 9));
613 /* bump max /var to make room for 2 crash dumps */
614 alloc[3].maxsz += 2 * (physmem / DEV_BSIZE(1 << 9));
615 }
616
617 xtrasecs = editor_countfree(lp);
618
619 for (i = 0; i < lastalloc; i++) {
620 alloc[i].minsz = DL_BLKTOSEC(lp, alloc[i].minsz)((alloc[i].minsz) / ((lp)->d_secsize / (1 << 9)));
621 alloc[i].maxsz = DL_BLKTOSEC(lp, alloc[i].maxsz)((alloc[i].maxsz) / ((lp)->d_secsize / (1 << 9)));
622 if (xtrasecs >= alloc[i].minsz)
623 xtrasecs -= alloc[i].minsz;
624 else {
625 /* It did not work out, try next strategy */
626 goto again;
627 }
628 }
629
630 for (i = 0; i < lastalloc; i++) {
631 /* Find next available partition. */
632 for (j = 0; j < MAXPARTITIONS16; j++)
633 if (DL_GETPSIZE(&lp->d_partitions[j])(((u_int64_t)(&lp->d_partitions[j])->p_sizeh <<
32) + (&lp->d_partitions[j])->p_size)
== 0)
634 break;
635 if (j == MAXPARTITIONS16) {
636 /* It did not work out, try next strategy */
637 goto again;
638 }
639 partno = j;
640 pp = &lp->d_partitions[j];
641 partmp = &mountpoints[j];
642 ap = &alloc[i];
643
644 /* Find largest chunk of free space. */
645 chunks = free_chunks(lp);
646 chunksize = 0;
647 for (j = 0; chunks[j].start != 0 || chunks[j].stop != 0; j++) {
648 if ((chunks[j].stop - chunks[j].start) > chunksize) {
649 chunkstart = chunks[j].start;
650 chunkstop = chunks[j].stop;
651#ifdef SUN_CYLCHECK
652 if (lp->d_flags & D_VENDOR0x08) {
653 /* Align to cylinder boundaries. */
654 chunkstart = ((chunkstart + cylsecs - 1)
655 / cylsecs) * cylsecs;
656 chunkstop = (chunkstop / cylsecs) *
657 cylsecs;
658 }
659#endif
660 chunksize = chunkstop - chunkstart;
661 }
662 }
663
664 /* Figure out the size of the partition. */
665 if (i == lastalloc - 1) {
666 if (chunksize > ap->maxsz)
667 secs = ap->maxsz;
668 else
669 secs = chunksize;
670 } else {
671 secs = ap->minsz;
672 if (xtrasecs > 0)
673 secs += (xtrasecs / 100) * ap->rate;
674 if (secs > ap->maxsz)
675 secs = ap->maxsz;
676 }
677#ifdef SUN_CYLCHECK
678 if (lp->d_flags & D_VENDOR0x08) {
679 secs = ((secs + cylsecs - 1) / cylsecs) * cylsecs;
680 while (secs > chunksize)
681 secs -= cylsecs;
682 }
683#endif
684
685 /* See if partition can fit into chunk. */
686 if (secs > chunksize)
687 secs = chunksize;
688 if (secs < ap->minsz) {
689 /* It did not work out, try next strategy */
690 goto again;
691 }
692
693 /* Everything seems ok so configure the partition. */
694 DL_SETPSIZE(pp, secs)do { u_int64_t __x = (secs); (pp)->p_sizeh = __x >> 32
; (pp)->p_size = __x; } while (0)
;
695 DL_SETPOFFSET(pp, chunkstart)do { u_int64_t __x = (chunkstart); (pp)->p_offseth = __x >>
32; (pp)->p_offset = __x; } while (0)
;
696 if (ap->mp[0] != '/')
697 pp->p_fstype = FS_SWAP1;
698 else {
699 pp->p_fstype = FS_BSDFFS7;
700 pp->p_fragblock = 0;
701 if (get_fsize(lp, partno) == 1 ||
702 get_bsize(lp, partno) == 1 ||
703 get_cpg(lp, partno) == 1) {
704 free(alloc);
705 return 1;
706 }
707 free(*partmp);
708 if ((*partmp = strdup(ap->mp)) == NULL((void *)0))
709 errx(4, "out of memory");
710 }
711 }
712
713 free(alloc);
714 memcpy(lp_org, lp, sizeof(struct disklabel));
715 return 0;
716}
717
718/*
719 * Resize a partition, moving all subsequent partitions
720 */
721void
722editor_resize(struct disklabel *lp, char *p)
723{
724 struct disklabel label;
725 struct partition *pp, *prev;
726 u_int64_t ui, sz, off;
727 int partno, i, flags, shrunk;
728
729 label = *lp;
730
731 /* Change which partition? */
732 if (p == NULL((void *)0))
30
Assuming 'p' is not equal to NULL
31
Taking false branch
733 p = getstring("partition to resize",
734 "The letter of the partition to name, a - p.", NULL((void *)0));
735 if (p
31.1
'p' is not equal to NULL
== NULL((void *)0))
32
Taking false branch
736 return;
737 partno = p[0] - 'a';
738 if (partno < 0 || partno == RAW_PART2 || partno >= lp->d_npartitions) {
33
Assuming 'partno' is >= 0
34
Assuming 'partno' is not equal to RAW_PART
35
Assuming 'partno' is < field 'd_npartitions'
36
Taking false branch
739 fprintf(stderr(&__sF[2]), "Partition must be between 'a' and '%c' "
740 "(excluding 'c').\n", 'a' + lp->d_npartitions - 1);
741 return;
742 }
743
744 pp = &label.d_partitions[partno];
745 sz = DL_GETPSIZE(pp)(((u_int64_t)(pp)->p_sizeh << 32) + (pp)->p_size);
746 if (sz == 0) {
37
Assuming 'sz' is not equal to 0
38
Taking false branch
747 fputs("No such partition\n", stderr(&__sF[2]));
748 return;
749 }
750 if (pp->p_fstype != FS_BSDFFS7 && pp->p_fstype != FS_SWAP1) {
39
Assuming field 'p_fstype' is equal to FS_BSDFFS
751 fputs("Cannot resize spoofed partition\n", stderr(&__sF[2]));
752 return;
753 }
754 flags = DO_CONVERSIONS0x00000001;
755 ui = getuint64(lp, "[+|-]new size (with unit)",
756 "new size or amount to grow (+) or shrink (-) partition including "
757 "unit", sz, sz + editor_countfree(lp), &flags);
758
759 if (ui == CMD_ABORTED((9223372036854775807LL*2ULL+1ULL) - 1))
40
Assuming the condition is false
41
Taking false branch
760 return;
761 else if (ui == CMD_BADVALUE((9223372036854775807LL*2ULL+1ULL)))
42
Assuming the condition is false
43
Taking false branch
762 return;
763 else if (ui == 0) {
44
Assuming 'ui' is not equal to 0
45
Taking false branch
764 fputs("The size must be > 0 sectors\n", stderr(&__sF[2]));
765 return;
766 }
767
768#ifdef SUN_CYLCHECK
769 if (lp->d_secpercyl & D_VENDOR0x08) {
770 u_int64_t cylsecs;
771 cylsecs = lp->d_secpercyl;
772 ui = ((ui + cylsecs - 1) / cylsecs) * cylsecs;
773 }
774#endif
775 if (DL_GETPOFFSET(pp)(((u_int64_t)(pp)->p_offseth << 32) + (pp)->p_offset
)
+ ui > ending_sector
) {
46
Assuming the condition is false
47
Taking false branch
776 fputs("Amount too big\n", stderr(&__sF[2]));
777 return;
778 }
779
780 DL_SETPSIZE(pp, ui)do { u_int64_t __x = (ui); (pp)->p_sizeh = __x >> 32
; (pp)->p_size = __x; } while (0)
;
48
Loop condition is false. Exiting loop
781 pp->p_fragblock = 0;
782 if (get_fsize(&label, partno) == 1 ||
783 get_bsize(&label, partno) == 1 ||
49
Calling 'get_bsize'
784 get_cpg(&label, partno) == 1)
785 return;
786
787 /*
788 * Pack partitions above the resized partition, leaving unused
789 * partitions alone.
790 */
791 shrunk = -1;
792 prev = pp;
793 for (i = partno + 1; i < MAXPARTITIONS16; i++) {
794 if (i == RAW_PART2)
795 continue;
796 pp = &label.d_partitions[i];
797 if (pp->p_fstype != FS_BSDFFS7 && pp->p_fstype != FS_SWAP1)
798 continue;
799 sz = DL_GETPSIZE(pp)(((u_int64_t)(pp)->p_sizeh << 32) + (pp)->p_size);
800 if (sz == 0)
801 continue;
802
803 off = DL_GETPOFFSET(prev)(((u_int64_t)(prev)->p_offseth << 32) + (prev)->p_offset
)
+ DL_GETPSIZE(prev)(((u_int64_t)(prev)->p_sizeh << 32) + (prev)->p_size
)
;
804
805 if (off < ending_sector) {
806 DL_SETPOFFSET(pp, off)do { u_int64_t __x = (off); (pp)->p_offseth = __x >>
32; (pp)->p_offset = __x; } while (0)
;
807 if (off + DL_GETPSIZE(pp)(((u_int64_t)(pp)->p_sizeh << 32) + (pp)->p_size) > ending_sector) {
808 DL_SETPSIZE(pp, ending_sector - off)do { u_int64_t __x = (ending_sector - off); (pp)->p_sizeh =
__x >> 32; (pp)->p_size = __x; } while (0)
;
809 pp->p_fragblock = DISKLABELV1_FFS_FRAGBLOCK(0, 0)((0) * (0) == 0 ? 0 : (((ffs((0) * (0)) - 13) << 3) | (
ffs(0))))
;
810 if (get_fsize(&label, i) == 1 ||
811 get_bsize(&label, i) == 1 ||
812 get_cpg(&label, i) == 1)
813 return;
814 shrunk = i;
815 }
816 } else {
817 fputs("Amount too big\n", stderr(&__sF[2]));
818 return;
819 }
820 prev = pp;
821 }
822
823 if (shrunk != -1)
824 fprintf(stderr(&__sF[2]), "Partition %c shrunk to %llu sectors to make "
825 "room\n", 'a' + shrunk,
826 DL_GETPSIZE(&label.d_partitions[shrunk])(((u_int64_t)(&label.d_partitions[shrunk])->p_sizeh <<
32) + (&label.d_partitions[shrunk])->p_size)
);
827 *lp = label;
828}
829
830/*
831 * Add a new partition.
832 */
833void
834editor_add(struct disklabel *lp, char *p)
835{
836 struct partition *pp;
837 struct diskchunk *chunks;
838 char buf[2];
839 int i, partno;
840 u_int64_t freesectors, new_offset, new_size;
841
842 freesectors = editor_countfree(lp);
843
844 /* XXX - prompt user to steal space from another partition instead */
845#ifdef SUN_CYLCHECK
846 if ((lp->d_flags & D_VENDOR0x08) && freesectors < lp->d_secpercyl) {
847 fputs("No space left, you need to shrink a partition "
848 "(need at least one full cylinder)\n",
849 stderr(&__sF[2]));
850 return;
851 }
852#endif
853 if (freesectors == 0) {
854 fputs("No space left, you need to shrink a partition\n",
855 stderr(&__sF[2]));
856 return;
857 }
858
859 if (p == NULL((void *)0)) {
860 /*
861 * Use the first unused partition that is not 'c' as the
862 * default partition in the prompt string.
863 */
864 pp = &lp->d_partitions[0];
865 buf[0] = buf[1] = '\0';
866 for (partno = 0; partno < MAXPARTITIONS16; partno++, pp++) {
867 if (DL_GETPSIZE(pp)(((u_int64_t)(pp)->p_sizeh << 32) + (pp)->p_size) == 0 && partno != RAW_PART2) {
868 buf[0] = partno + 'a';
869 p = &buf[0];
870 break;
871 }
872 }
873 p = getstring("partition",
874 "The letter of the new partition, a - p.", p);
875 }
876 if (p == NULL((void *)0))
877 return;
878 partno = p[0] - 'a';
879 if (partno < 0 || partno == RAW_PART2 || partno >= MAXPARTITIONS16) {
880 fprintf(stderr(&__sF[2]), "Partition must be between 'a' and '%c' "
881 "(excluding 'c').\n", 'a' + MAXPARTITIONS16 - 1);
882 return;
883 }
884 pp = &lp->d_partitions[partno];
885
886 if (pp->p_fstype != FS_UNUSED0 && DL_GETPSIZE(pp)(((u_int64_t)(pp)->p_sizeh << 32) + (pp)->p_size) != 0) {
887 fprintf(stderr(&__sF[2]), "Partition '%c' exists. Delete it first.\n",
888 p[0]);
889 return;
890 }
891
892 /*
893 * Increase d_npartitions if necessary. Ensure all new partitions are
894 * zero'ed to avoid inadvertent overlaps.
895 */
896 for(; lp->d_npartitions <= partno; lp->d_npartitions++)
897 memset(&lp->d_partitions[lp->d_npartitions], 0, sizeof(*pp));
898
899 /* Make sure selected partition is zero'd too. */
900 memset(pp, 0, sizeof(*pp));
901 chunks = free_chunks(lp);
902
903 /*
904 * Since we know there's free space, there must be at least one
905 * chunk. So find the largest chunk and assume we want to add the
906 * partition in that free space.
907 */
908 new_size = new_offset = 0;
909 for (i = 0; chunks[i].start != 0 || chunks[i].stop != 0; i++) {
910 if (chunks[i].stop - chunks[i].start > new_size) {
911 new_size = chunks[i].stop - chunks[i].start;
912 new_offset = chunks[i].start;
913 }
914 }
915 DL_SETPSIZE(pp, new_size)do { u_int64_t __x = (new_size); (pp)->p_sizeh = __x >>
32; (pp)->p_size = __x; } while (0)
;
916 DL_SETPOFFSET(pp, new_offset)do { u_int64_t __x = (new_offset); (pp)->p_offseth = __x >>
32; (pp)->p_offset = __x; } while (0)
;
917 pp->p_fstype = partno == 1 ? FS_SWAP1 : FS_BSDFFS7;
918
919 if (get_offset(lp, partno) == 0 &&
920 get_size(lp, partno) == 0 &&
921 get_fstype(lp, partno) == 0 &&
922 get_mp(lp, partno) == 0 &&
923 get_fsize(lp, partno) == 0 &&
924 get_bsize(lp, partno) == 0 &&
925 get_cpg(lp, partno) == 0)
926 return;
927
928 /* Bailed out at some point, so effectively delete the partition. */
929 memset(pp, 0, sizeof(*pp));
930}
931
932/*
933 * Set the mountpoint of an existing partition ('name').
934 */
935void
936editor_name(struct disklabel *lp, char *p)
937{
938 struct partition *pp;
939 int partno;
940
941 /* Change which partition? */
942 if (p == NULL((void *)0))
943 p = getstring("partition to name",
944 "The letter of the partition to name, a - p.", NULL((void *)0));
945 if (p == NULL((void *)0))
946 return;
947 partno = p[0] - 'a';
948 if (partno < 0 || partno == RAW_PART2 || partno >= lp->d_npartitions) {
949 fprintf(stderr(&__sF[2]), "Partition must be between 'a' and '%c' "
950 "(excluding 'c').\n", 'a' + lp->d_npartitions - 1);
951 return;
952 }
953 pp = &lp->d_partitions[partno];
954
955 if (pp->p_fstype == FS_UNUSED0 && DL_GETPSIZE(pp)(((u_int64_t)(pp)->p_sizeh << 32) + (pp)->p_size) == 0) {
956 fprintf(stderr(&__sF[2]), "Partition '%c' is not in use.\n", p[0]);
957 return;
958 }
959
960 get_mp(lp, partno);
961}
962
963/*
964 * Change an existing partition.
965 */
966void
967editor_modify(struct disklabel *lp, char *p)
968{
969 struct partition opp, *pp;
970 int partno;
971
972 /* Change which partition? */
973 if (p == NULL((void *)0))
974 p = getstring("partition to modify",
975 "The letter of the partition to modify, a - p.", NULL((void *)0));
976 if (p == NULL((void *)0))
977 return;
978 partno = p[0] - 'a';
979 if (partno < 0 || partno == RAW_PART2 || partno >= lp->d_npartitions) {
980 fprintf(stderr(&__sF[2]), "Partition must be between 'a' and '%c' "
981 "(excluding 'c').\n", 'a' + lp->d_npartitions - 1);
982 return;
983 }
984 pp = &lp->d_partitions[partno];
985
986 if (pp->p_fstype == FS_UNUSED0 && DL_GETPSIZE(pp)(((u_int64_t)(pp)->p_sizeh << 32) + (pp)->p_size) == 0) {
987 fprintf(stderr(&__sF[2]), "Partition '%c' is not in use.\n", p[0]);
988 return;
989 }
990
991 opp = *pp;
992
993 if (get_offset(lp, partno) == 0 &&
994 get_size(lp, partno) == 0 &&
995 get_fstype(lp, partno) == 0 &&
996 get_mp(lp, partno) == 0 &&
997 get_fsize(lp, partno) == 0 &&
998 get_bsize(lp, partno) == 0 &&
999 get_cpg(lp, partno) == 0)
1000 return;
1001
1002 /* Bailed out at some point, so undo any changes. */
1003 *pp = opp;
1004}
1005
1006/*
1007 * Delete an existing partition.
1008 */
1009void
1010editor_delete(struct disklabel *lp, char *p)
1011{
1012 struct partition *pp;
1013 int partno;
1014
1015 if (p == NULL((void *)0))
1016 p = getstring("partition to delete",
1017 "The letter of the partition to delete, a - p, or '*'.",
1018 NULL((void *)0));
1019 if (p == NULL((void *)0))
1020 return;
1021 if (p[0] == '*') {
1022 zero_partitions(lp);
1023 return;
1024 }
1025 partno = p[0] - 'a';
1026 if (partno < 0 || partno == RAW_PART2 || partno >= lp->d_npartitions) {
1027 fprintf(stderr(&__sF[2]), "Partition must be between 'a' and '%c' "
1028 "(excluding 'c').\n", 'a' + lp->d_npartitions - 1);
1029 return;
1030 }
1031 pp = &lp->d_partitions[partno];
1032
1033 if (pp->p_fstype == FS_UNUSED0 && DL_GETPSIZE(pp)(((u_int64_t)(pp)->p_sizeh << 32) + (pp)->p_size) == 0) {
1034 fprintf(stderr(&__sF[2]), "Partition '%c' is not in use.\n", p[0]);
1035 return;
1036 }
1037
1038 /* Really delete it (as opposed to just setting to "unused") */
1039 memset(pp, 0, sizeof(*pp));
1040 free(mountpoints[partno]);
1041 mountpoints[partno] = NULL((void *)0);
1042}
1043
1044/*
1045 * Change the size of an existing partition.
1046 */
1047void
1048editor_change(struct disklabel *lp, char *p)
1049{
1050 struct partition *pp;
1051 int partno;
1052
1053 if (p == NULL((void *)0))
1054 p = getstring("partition to change size",
1055 "The letter of the partition to change size, a - p.", NULL((void *)0));
1056 if (p == NULL((void *)0))
1057 return;
1058 partno = p[0] - 'a';
1059 if (partno < 0 || partno == RAW_PART2 || partno >= lp->d_npartitions) {
1060 fprintf(stderr(&__sF[2]), "Partition must be between 'a' and '%c' "
1061 "(excluding 'c').\n", 'a' + lp->d_npartitions - 1);
1062 return;
1063 }
1064 pp = &lp->d_partitions[partno];
1065
1066 if (DL_GETPSIZE(pp)(((u_int64_t)(pp)->p_sizeh << 32) + (pp)->p_size) == 0) {
1067 fprintf(stderr(&__sF[2]), "Partition '%c' is not in use.\n", p[0]);
1068 return;
1069 }
1070
1071 printf("Partition %c is currently %llu sectors in size, and can have "
1072 "a maximum\nsize of %llu sectors.\n",
1073 p[0], DL_GETPSIZE(pp)(((u_int64_t)(pp)->p_sizeh << 32) + (pp)->p_size), max_partition_size(lp, partno));
1074
1075 /* Get new size */
1076 get_size(lp, partno);
1077}
1078
1079/*
1080 * Sort the partitions based on starting offset.
1081 * This assumes there can be no overlap.
1082 */
1083int
1084partition_cmp(const void *e1, const void *e2)
1085{
1086 struct partition *p1 = *(struct partition **)e1;
1087 struct partition *p2 = *(struct partition **)e2;
1088 u_int64_t o1 = DL_GETPOFFSET(p1)(((u_int64_t)(p1)->p_offseth << 32) + (p1)->p_offset
)
;
1089 u_int64_t o2 = DL_GETPOFFSET(p2)(((u_int64_t)(p2)->p_offseth << 32) + (p2)->p_offset
)
;
1090
1091 if (o1 < o2)
1092 return -1;
1093 else if (o1 > o2)
1094 return 1;
1095 else
1096 return 0;
1097}
1098
1099char *
1100getstring(const char *prompt, const char *helpstring, const char *oval)
1101{
1102 static char buf[BUFSIZ1024];
1103 int n;
1104
1105 buf[0] = '\0';
1106 do {
1107 printf("%s: [%s] ", prompt, oval ? oval : "");
1108 if (fgets(buf, sizeof(buf), stdin(&__sF[0])) == NULL((void *)0)) {
1109 buf[0] = '\0';
1110 if (feof(stdin)(!__isthreaded ? ((((&__sF[0]))->_flags & 0x0020) !=
0) : (feof)((&__sF[0])))
) {
1111 clearerr(stdin)(!__isthreaded ? ((void)(((&__sF[0]))->_flags &= ~
(0x0040|0x0020))) : (clearerr)((&__sF[0])))
;
1112 putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
1113 fputs("Command aborted\n", stderr(&__sF[2]));
1114 return (NULL((void *)0));
1115 }
1116 }
1117 n = strlen(buf);
1118 if (n > 0 && buf[n-1] == '\n')
1119 buf[--n] = '\0';
1120 if (buf[0] == '?')
1121 puts(helpstring);
1122 else if (oval != NULL((void *)0) && buf[0] == '\0')
1123 strlcpy(buf, oval, sizeof(buf));
1124 } while (buf[0] == '?');
1125
1126 return (&buf[0]);
1127}
1128
1129/*
1130 * Returns
1131 * 0 .. CMD_ABORTED - 1 ==> valid value
1132 * CMD_BADVALUE ==> invalid value
1133 * CMD_ABORTED ==> ^D on input
1134 */
1135u_int64_t
1136getnumber(char *prompt, char *helpstring, u_int32_t oval, u_int32_t maxval)
1137{
1138 char buf[BUFSIZ1024], *p;
1139 int rslt;
1140 long long rval;
1141 const char *errstr;
1142
1143 rslt = snprintf(buf, sizeof(buf), "%u", oval);
1144 if (rslt < 0 || (unsigned int)rslt >= sizeof(buf))
1145 return (CMD_BADVALUE((9223372036854775807LL*2ULL+1ULL)));
1146
1147 p = getstring(prompt, helpstring, buf);
1148 if (p == NULL((void *)0))
1149 return (CMD_ABORTED((9223372036854775807LL*2ULL+1ULL) - 1));
1150 if (strlen(p) == 0)
1151 return (oval);
1152
1153 rval = strtonum(p, 0, maxval, &errstr);
1154 if (errstr != NULL((void *)0)) {
1155 printf("%s must be between 0 and %u\n", prompt, maxval);
1156 return (CMD_BADVALUE((9223372036854775807LL*2ULL+1ULL)));
1157 }
1158
1159 return (rval);
1160}
1161
1162/*
1163 * Returns
1164 * 0 .. CMD_ABORTED - 1 ==> valid value
1165 * CMD_BADVALUE ==> invalid value
1166 * CMD_ABORTED ==> ^D on input
1167 */
1168u_int64_t
1169getuint64(struct disklabel *lp, char *prompt, char *helpstring,
1170 u_int64_t oval, u_int64_t maxval, int *flags)
1171{
1172 char buf[21], *p, operator = '\0';
1173 char *unit = NULL((void *)0);
1174 u_int64_t rval = oval;
1175 double d;
1176 int rslt;
1177
1178 rslt = snprintf(buf, sizeof(buf), "%llu", oval);
1179 if (rslt < 0 || (unsigned int)rslt >= sizeof(buf))
1180 goto invalid;
1181
1182 p = getstring(prompt, helpstring, buf);
1183 if (p == NULL((void *)0))
1184 return (CMD_ABORTED((9223372036854775807LL*2ULL+1ULL) - 1));
1185 else if (p[0] == '\0')
1186 rval = oval;
1187 else if (p[0] == '*' && p[1] == '\0')
1188 rval = maxval;
1189 else {
1190 if (*p == '+' || *p == '-')
1191 operator = *p++;
1192 if (parse_sizespec(p, &d, &unit) == -1)
1193 goto invalid;
1194 if (unit == NULL((void *)0))
1195 rval = d;
1196 else if (flags != NULL((void *)0) && (*flags & DO_CONVERSIONS0x00000001) == 0)
1197 goto invalid;
1198 else {
1199 switch (tolower((unsigned char)*unit)) {
1200 case 'b':
1201 rval = d / lp->d_secsize;
1202 break;
1203 case 'c':
1204 rval = d * lp->d_secpercyl;
1205 break;
1206 case '%':
1207 rval = DL_GETDSIZE(lp)(((u_int64_t)(lp)->d_secperunith << 32) + (lp)->d_secperunit
)
* (d / 100.0);
1208 break;
1209 case '&':
1210 rval = maxval * (d / 100.0);
1211 break;
1212 default:
1213 if (apply_unit(d, *unit, &rval) == -1)
1214 goto invalid;
1215 rval = DL_BLKTOSEC(lp, rval)((rval) / ((lp)->d_secsize / (1 << 9)));
1216 break;
1217 }
1218 }
1219
1220 /* Range check then apply [+-] operator */
1221 if (operator == '+') {
1222 if (CMD_ABORTED((9223372036854775807LL*2ULL+1ULL) - 1) - oval > rval)
1223 rval += oval;
1224 else {
1225 goto invalid;
1226 }
1227 } else if (operator == '-') {
1228 if (oval >= rval)
1229 rval = oval - rval;
1230 else {
1231 goto invalid;
1232 }
1233 }
1234 }
1235
1236 if (flags != NULL((void *)0)) {
1237 if (unit != NULL((void *)0))
1238 *flags |= DO_ROUNDING0x00000002;
1239#ifdef SUN_CYLCHECK
1240 if (lp->d_flags & D_VENDOR0x08)
1241 *flags |= DO_ROUNDING0x00000002;
1242#endif
1243 }
1244 return (rval);
1245
1246invalid:
1247 fputs("Invalid entry\n", stderr(&__sF[2]));
1248 return (CMD_BADVALUE((9223372036854775807LL*2ULL+1ULL)));
1249}
1250
1251/*
1252 * Check for partition overlap in lp and prompt the user to resolve the overlap
1253 * if any is found. Returns 1 if unable to resolve, else 0.
1254 */
1255int
1256has_overlap(struct disklabel *lp)
1257{
1258 struct partition **spp;
1259 int i, p1, p2;
1260 char *line = NULL((void *)0);
1261 size_t linesize = 0;
1262 ssize_t linelen;
1263
1264 for (;;) {
1265 spp = sort_partitions(lp);
1266 for (i = 0; spp[i+1] != NULL((void *)0); i++) {
1267 if (DL_GETPOFFSET(spp[i])(((u_int64_t)(spp[i])->p_offseth << 32) + (spp[i])->
p_offset)
+ DL_GETPSIZE(spp[i])(((u_int64_t)(spp[i])->p_sizeh << 32) + (spp[i])->
p_size)
>
1268 DL_GETPOFFSET(spp[i+1])(((u_int64_t)(spp[i+1])->p_offseth << 32) + (spp[i+1
])->p_offset)
)
1269 break;
1270 }
1271 if (spp[i+1] == NULL((void *)0)) {
1272 free(line);
1273 return (0);
1274 }
1275
1276 p1 = 'a' + (spp[i] - lp->d_partitions);
1277 p2 = 'a' + (spp[i+1] - lp->d_partitions);
1278 printf("\nError, partitions %c and %c overlap:\n", p1, p2);
1279 printf("# %16.16s %16.16s fstype [fsize bsize cpg]\n",
1280 "size", "offset");
1281 display_partition(stdout(&__sF[1]), lp, p1 - 'a', 0);
1282 display_partition(stdout(&__sF[1]), lp, p2 - 'a', 0);
1283
1284 for (;;) {
1285 printf("Disable which one? (%c %c) ", p1, p2);
1286 linelen = getline(&line, &linesize, stdin(&__sF[0]));
1287 if (linelen == -1)
1288 goto done;
1289 if (linelen == 2 && (line[0] == p1 || line[0] == p2))
1290 break;
1291 }
1292 lp->d_partitions[line[0] - 'a'].p_fstype = FS_UNUSED0;
1293 }
1294
1295done:
1296 putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
1297 free(line);
1298 return (1);
1299}
1300
1301void
1302edit_parms(struct disklabel *lp)
1303{
1304 char *p;
1305 u_int64_t freesectors, ui;
1306 struct disklabel oldlabel = *lp;
1307
1308 printf("Changing device parameters for %s:\n", specname);
1309
1310 /* disk type */
1311 for (;;) {
1312 p = getstring("disk type",
1313 "What kind of disk is this? Usually SCSI, ESDI, ST506, or "
1314 "floppy (use ESDI for IDE).", dktypenames[lp->d_type]);
1315 if (p == NULL((void *)0))
1316 return;
1317 if (strcasecmp(p, "IDE") == 0)
1318 ui = DTYPE_ESDI5;
1319 else
1320 for (ui = 1; ui < DKMAXTYPES(sizeof(dktypenames) / sizeof(dktypenames[0]) - 1) && strcasecmp(p,
1321 dktypenames[ui]); ui++)
1322 ;
1323 if (ui < DKMAXTYPES(sizeof(dktypenames) / sizeof(dktypenames[0]) - 1)) {
1324 break;
1325 } else {
1326 printf("\"%s\" is not a valid disk type.\n", p);
1327 fputs("Valid types are: ", stdout(&__sF[1]));
1328 for (ui = 1; ui < DKMAXTYPES(sizeof(dktypenames) / sizeof(dktypenames[0]) - 1); ui++) {
1329 printf("\"%s\"", dktypenames[ui]);
1330 if (ui < DKMAXTYPES(sizeof(dktypenames) / sizeof(dktypenames[0]) - 1) - 1)
1331 fputs(", ", stdout(&__sF[1]));
1332 }
1333 putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
1334 }
1335 }
1336 lp->d_type = ui;
1337
1338 /* pack/label id */
1339 p = getstring("label name",
1340 "15 char string that describes this label, usually the disk name.",
1341 lp->d_packname);
1342 if (p == NULL((void *)0)) {
1343 *lp = oldlabel; /* undo damage */
1344 return;
1345 }
1346 strncpy(lp->d_packname, p, sizeof(lp->d_packname)); /* checked */
1347
1348 /* sectors/track */
1349 for (;;) {
1350 ui = getnumber("sectors/track",
1351 "The Number of sectors per track.", lp->d_nsectors,
1352 UINT32_MAX0xffffffffU);
1353 if (ui == CMD_ABORTED((9223372036854775807LL*2ULL+1ULL) - 1)) {
1354 *lp = oldlabel; /* undo damage */
1355 return;
1356 } else if (ui == CMD_BADVALUE((9223372036854775807LL*2ULL+1ULL)))
1357 ; /* Try again. */
1358 else
1359 break;
1360 }
1361 lp->d_nsectors = ui;
1362
1363 /* tracks/cylinder */
1364 for (;;) {
1365 ui = getnumber("tracks/cylinder",
1366 "The number of tracks per cylinder.", lp->d_ntracks,
1367 UINT32_MAX0xffffffffU);
1368 if (ui == CMD_ABORTED((9223372036854775807LL*2ULL+1ULL) - 1)) {
1369 *lp = oldlabel; /* undo damage */
1370 return;
1371 } else if (ui == CMD_BADVALUE((9223372036854775807LL*2ULL+1ULL)))
1372 ; /* Try again. */
1373 else
1374 break;
1375 }
1376 lp->d_ntracks = ui;
1377
1378 /* sectors/cylinder */
1379 for (;;) {
1380 ui = getnumber("sectors/cylinder",
1381 "The number of sectors per cylinder (Usually sectors/track "
1382 "* tracks/cylinder).", lp->d_secpercyl, UINT32_MAX0xffffffffU);
1383 if (ui == CMD_ABORTED((9223372036854775807LL*2ULL+1ULL) - 1)) {
1384 *lp = oldlabel; /* undo damage */
1385 return;
1386 } else if (ui == CMD_BADVALUE((9223372036854775807LL*2ULL+1ULL)))
1387 ; /* Try again. */
1388 else
1389 break;
1390 }
1391 lp->d_secpercyl = ui;
1392
1393 /* number of cylinders */
1394 for (;;) {
1395 ui = getnumber("number of cylinders",
1396 "The total number of cylinders on the disk.",
1397 lp->d_ncylinders, UINT32_MAX0xffffffffU);
1398 if (ui == CMD_ABORTED((9223372036854775807LL*2ULL+1ULL) - 1)) {
1399 *lp = oldlabel; /* undo damage */
1400 return;
1401 } else if (ui == CMD_BADVALUE((9223372036854775807LL*2ULL+1ULL)))
1402 ; /* Try again. */
1403 else
1404 break;
1405 }
1406 lp->d_ncylinders = ui;
1407
1408 /* total sectors */
1409 for (;;) {
1410 u_int64_t nsec = MAXIMUM(DL_GETDSIZE(lp),((((((u_int64_t)(lp)->d_secperunith << 32) + (lp)->
d_secperunit)) > ((u_int64_t)lp->d_ncylinders * lp->
d_secpercyl)) ? ((((u_int64_t)(lp)->d_secperunith <<
32) + (lp)->d_secperunit)) : ((u_int64_t)lp->d_ncylinders
* lp->d_secpercyl))
1411 (u_int64_t)lp->d_ncylinders * lp->d_secpercyl)((((((u_int64_t)(lp)->d_secperunith << 32) + (lp)->
d_secperunit)) > ((u_int64_t)lp->d_ncylinders * lp->
d_secpercyl)) ? ((((u_int64_t)(lp)->d_secperunith <<
32) + (lp)->d_secperunit)) : ((u_int64_t)lp->d_ncylinders
* lp->d_secpercyl))
;
1412 ui = getuint64(lp, "total sectors",
1413 "The total number of sectors on the disk.",
1414 nsec, nsec, NULL((void *)0));
1415 if (ui == CMD_ABORTED((9223372036854775807LL*2ULL+1ULL) - 1)) {
1416 *lp = oldlabel; /* undo damage */
1417 return;
1418 } else if (ui == CMD_BADVALUE((9223372036854775807LL*2ULL+1ULL)))
1419 ; /* Try again. */
1420 else if (ui > DL_GETDSIZE(lp)(((u_int64_t)(lp)->d_secperunith << 32) + (lp)->d_secperunit
)
&&
1421 ending_sector == DL_GETDSIZE(lp)(((u_int64_t)(lp)->d_secperunith << 32) + (lp)->d_secperunit
)
) {
1422 puts("You may want to increase the size of the 'c' "
1423 "partition.");
1424 break;
1425 } else if (ui < DL_GETDSIZE(lp)(((u_int64_t)(lp)->d_secperunith << 32) + (lp)->d_secperunit
)
&&
1426 ending_sector == DL_GETDSIZE(lp)(((u_int64_t)(lp)->d_secperunith << 32) + (lp)->d_secperunit
)
) {
1427 /* shrink free count */
1428 freesectors = editor_countfree(lp);
1429 if (DL_GETDSIZE(lp)(((u_int64_t)(lp)->d_secperunith << 32) + (lp)->d_secperunit
)
- ui > freesectors)
1430 fprintf(stderr(&__sF[2]),
1431 "Not enough free space to shrink by %llu "
1432 "sectors (only %llu sectors left)\n",
1433 DL_GETDSIZE(lp)(((u_int64_t)(lp)->d_secperunith << 32) + (lp)->d_secperunit
)
- ui, freesectors);
1434 else
1435 break;
1436 } else
1437 break;
1438 }
1439 /* Adjust ending_sector if necessary. */
1440 if (ending_sector > ui) {
1441 ending_sector = ui;
1442 DL_SETBEND(lp, ending_sector)do { u_int64_t __x = (ending_sector); (lp)->d_bendh = __x >>
32; (lp)->d_bend = __x; } while (0)
;
1443 }
1444 DL_SETDSIZE(lp, ui)do { u_int64_t __x = (ui); (lp)->d_secperunith = __x >>
32; (lp)->d_secperunit = __x; } while (0)
;
1445}
1446
1447struct partition **
1448sort_partitions(struct disklabel *lp)
1449{
1450 static struct partition *spp[MAXPARTITIONS16+2];
1451 int i, npartitions;
1452
1453 memset(spp, 0, sizeof(spp));
1454
1455 for (npartitions = 0, i = 0; i < lp->d_npartitions; i++) {
1456 if (lp->d_partitions[i].p_fstype != FS_UNUSED0 &&
1457 DL_GETPSIZE(&lp->d_partitions[i])(((u_int64_t)(&lp->d_partitions[i])->p_sizeh <<
32) + (&lp->d_partitions[i])->p_size)
!= 0)
1458 spp[npartitions++] = &lp->d_partitions[i];
1459 }
1460
1461 /*
1462 * Sort the partitions based on starting offset.
1463 * This is safe because we guarantee no overlap.
1464 */
1465 if (npartitions > 1)
1466 if (mergesort((void *)spp, npartitions, sizeof(spp[0]),
1467 partition_cmp))
1468 err(4, "failed to sort partition table");
1469
1470 return (spp);
1471}
1472
1473/*
1474 * Get a valid disk type if necessary.
1475 */
1476void
1477getdisktype(struct disklabel *lp, char *banner, char *dev)
1478{
1479 int i;
1480 char *s;
1481 const char *def = "SCSI";
1482 const struct dtypes {
1483 const char *dev;
1484 const char *type;
1485 } dtypes[] = {
1486 { "sd", "SCSI" },
1487 { "wd", "IDE" },
1488 { "fd", "FLOPPY" },
1489 { "xd", "SMD" },
1490 { "xy", "SMD" },
1491 { "hd", "HP-IB" },
1492 { "vnd", "VND" },
1493 { "svnd", "VND" },
1494 { NULL((void *)0), NULL((void *)0) }
1495 };
1496
1497 if ((s = basename(dev)) != NULL((void *)0)) {
1498 if (*s == 'r')
1499 s++;
1500 i = strcspn(s, "0123456789");
1501 s[i] = '\0';
1502 dev = s;
1503 for (i = 0; dtypes[i].dev != NULL((void *)0); i++) {
1504 if (strcmp(dev, dtypes[i].dev) == 0) {
1505 def = dtypes[i].type;
1506 break;
1507 }
1508 }
1509 }
1510
1511 if (lp->d_type > DKMAXTYPES(sizeof(dktypenames) / sizeof(dktypenames[0]) - 1) || lp->d_type == 0) {
1512 puts(banner);
1513 puts("Possible values are:");
1514 printf("\"IDE\", ");
1515 for (i = 1; i < DKMAXTYPES(sizeof(dktypenames) / sizeof(dktypenames[0]) - 1); i++) {
1516 printf("\"%s\"", dktypenames[i]);
1517 if (i < DKMAXTYPES(sizeof(dktypenames) / sizeof(dktypenames[0]) - 1) - 1)
1518 fputs(", ", stdout(&__sF[1]));
1519 }
1520 putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
1521
1522 for (;;) {
1523 s = getstring("Disk type",
1524 "What kind of disk is this? Usually SCSI, IDE, "
1525 "ESDI, ST506, or floppy.", def);
1526 if (s == NULL((void *)0))
1527 continue;
1528 if (strcasecmp(s, "IDE") == 0) {
1529 lp->d_type = DTYPE_ESDI5;
1530 return;
1531 }
1532 for (i = 1; i < DKMAXTYPES(sizeof(dktypenames) / sizeof(dktypenames[0]) - 1); i++)
1533 if (strcasecmp(s, dktypenames[i]) == 0) {
1534 lp->d_type = i;
1535 return;
1536 }
1537 printf("\"%s\" is not a valid disk type.\n", s);
1538 fputs("Valid types are: ", stdout(&__sF[1]));
1539 for (i = 1; i < DKMAXTYPES(sizeof(dktypenames) / sizeof(dktypenames[0]) - 1); i++) {
1540 printf("\"%s\"", dktypenames[i]);
1541 if (i < DKMAXTYPES(sizeof(dktypenames) / sizeof(dktypenames[0]) - 1) - 1)
1542 fputs(", ", stdout(&__sF[1]));
1543 }
1544 putchar('\n')(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
1545 }
1546 }
1547}
1548
1549/*
1550 * Get beginning and ending sectors of the OpenBSD portion of the disk
1551 * from the user.
1552 */
1553void
1554set_bounds(struct disklabel *lp)
1555{
1556 u_int64_t ui, start_temp;
1557
1558 /* Starting sector */
1559 for (;;) {
1560 ui = getuint64(lp, "Starting sector",
1561 "The start of the OpenBSD portion of the disk.",
1562 starting_sector, DL_GETDSIZE(lp)(((u_int64_t)(lp)->d_secperunith << 32) + (lp)->d_secperunit
)
, NULL((void *)0));
1563 if (ui == CMD_ABORTED((9223372036854775807LL*2ULL+1ULL) - 1))
1564 return;
1565 else if (ui == CMD_BADVALUE((9223372036854775807LL*2ULL+1ULL)))
1566 ; /* Try again. */
1567 else if (ui >= DL_GETDSIZE(lp)(((u_int64_t)(lp)->d_secperunith << 32) + (lp)->d_secperunit
)
)
1568 fprintf(stderr(&__sF[2]), "starting sector must be < %llu\n",
1569 DL_GETDSIZE(lp)(((u_int64_t)(lp)->d_secperunith << 32) + (lp)->d_secperunit
)
);
1570 else
1571 break;
1572 }
1573 start_temp = ui;
1574
1575 /* Size */
1576 for (;;) {
1577 ui = getuint64(lp, "Size ('*' for entire disk)",
1578 "The size of the OpenBSD portion of the disk ('*' for the "
1579 "entire disk).", ending_sector - starting_sector,
1580 DL_GETDSIZE(lp)(((u_int64_t)(lp)->d_secperunith << 32) + (lp)->d_secperunit
)
- start_temp, NULL((void *)0));
1581 if (ui == CMD_ABORTED((9223372036854775807LL*2ULL+1ULL) - 1))
1582 return;
1583 else if (ui == CMD_BADVALUE((9223372036854775807LL*2ULL+1ULL)))
1584 ; /* Try again. */
1585 else if (ui > DL_GETDSIZE(lp)(((u_int64_t)(lp)->d_secperunith << 32) + (lp)->d_secperunit
)
- start_temp)
1586 fprintf(stderr(&__sF[2]), "size must be <= %llu\n",
1587 DL_GETDSIZE(lp)(((u_int64_t)(lp)->d_secperunith << 32) + (lp)->d_secperunit
)
- start_temp);
1588 else
1589 break;
1590 }
1591 ending_sector = start_temp + ui;
1592 DL_SETBEND(lp, ending_sector)do { u_int64_t __x = (ending_sector); (lp)->d_bendh = __x >>
32; (lp)->d_bend = __x; } while (0)
;
1593 starting_sector = start_temp;
1594 DL_SETBSTART(lp, starting_sector)do { u_int64_t __x = (starting_sector); (lp)->d_bstarth = __x
>> 32; (lp)->d_bstart = __x; } while (0)
;
1595}
1596
1597/*
1598 * Allow user to interactively change disklabel UID.
1599 */
1600void
1601set_duid(struct disklabel *lp)
1602{
1603 char *s;
1604 int i;
1605
1606 printf("The disklabel UID is currently: "
1607 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx\n",
1608 lp->d_uid[0], lp->d_uid[1], lp->d_uid[2], lp->d_uid[3],
1609 lp->d_uid[4], lp->d_uid[5], lp->d_uid[6], lp->d_uid[7]);
1610
1611 do {
1612 s = getstring("duid", "The disklabel UID, given as a 16 "
1613 "character hexadecimal string.", NULL((void *)0));
1614 if (s == NULL((void *)0) || strlen(s) == 0) {
1615 fputs("Command aborted\n", stderr(&__sF[2]));
1616 return;
1617 }
1618 i = duid_parse(lp, s);
1619 if (i != 0)
1620 fputs("Invalid UID entered.\n", stderr(&__sF[2]));
1621 } while (i != 0);
1622}
1623
1624/*
1625 * Return a list of the "chunks" of free space available
1626 */
1627struct diskchunk *
1628free_chunks(struct disklabel *lp)
1629{
1630 struct partition **spp;
1631 static struct diskchunk chunks[MAXPARTITIONS16 + 2];
1632 u_int64_t start, stop;
1633 int i, numchunks;
1634
1635 /* Sort the in-use partitions based on offset */
1636 spp = sort_partitions(lp);
1637
1638 /* If there are no partitions, it's all free. */
1639 if (spp[0] == NULL((void *)0)) {
1640 chunks[0].start = starting_sector;
1641 chunks[0].stop = ending_sector;
1642 chunks[1].start = chunks[1].stop = 0;
1643 return (chunks);
1644 }
1645
1646 /* Find chunks of free space */
1647 numchunks = 0;
1648 if (DL_GETPOFFSET(spp[0])(((u_int64_t)(spp[0])->p_offseth << 32) + (spp[0])->
p_offset)
> starting_sector) {
1649 chunks[0].start = starting_sector;
1650 chunks[0].stop = DL_GETPOFFSET(spp[0])(((u_int64_t)(spp[0])->p_offseth << 32) + (spp[0])->
p_offset)
;
1651 numchunks++;
1652 }
1653 for (i = 0; spp[i] != NULL((void *)0); i++) {
1654 start = DL_GETPOFFSET(spp[i])(((u_int64_t)(spp[i])->p_offseth << 32) + (spp[i])->
p_offset)
+ DL_GETPSIZE(spp[i])(((u_int64_t)(spp[i])->p_sizeh << 32) + (spp[i])->
p_size)
;
1655 if (start < starting_sector)
1656 start = starting_sector;
1657 else if (start > ending_sector)
1658 start = ending_sector;
1659 if (spp[i + 1] != NULL((void *)0))
1660 stop = DL_GETPOFFSET(spp[i+1])(((u_int64_t)(spp[i+1])->p_offseth << 32) + (spp[i+1
])->p_offset)
;
1661 else
1662 stop = ending_sector;
1663 if (stop < starting_sector)
1664 stop = starting_sector;
1665 else if (stop > ending_sector)
1666 stop = ending_sector;
1667 if (start < stop) {
1668 chunks[numchunks].start = start;
1669 chunks[numchunks].stop = stop;
1670 numchunks++;
1671 }
1672 }
1673
1674 /* Terminate and return */
1675 chunks[numchunks].start = chunks[numchunks].stop = 0;
1676 return (chunks);
1677}
1678
1679void
1680find_bounds(struct disklabel *lp)
1681{
1682 starting_sector = DL_GETBSTART(lp)(((u_int64_t)(lp)->d_bstarth << 32) + (lp)->d_bstart
)
;
1683 ending_sector = DL_GETBEND(lp)(((u_int64_t)(lp)->d_bendh << 32) + (lp)->d_bend);
1684
1685 if (ending_sector) {
1686 if (verbose)
1687 printf("Treating sectors %llu-%llu as the OpenBSD"
1688 " portion of the disk.\nYou can use the 'b'"
1689 " command to change this.\n\n", starting_sector,
1690 ending_sector);
1691 }
1692}
1693
1694/*
1695 * Calculate free space.
1696 */
1697u_int64_t
1698editor_countfree(struct disklabel *lp)
1699{
1700 struct diskchunk *chunks;
1701 u_int64_t freesectors = 0;
1702 int i;
1703
1704 chunks = free_chunks(lp);
1705
1706 for (i = 0; chunks[i].start != 0 || chunks[i].stop != 0; i++)
1707 freesectors += chunks[i].stop - chunks[i].start;
1708
1709 return (freesectors);
1710}
1711
1712void
1713editor_help(void)
1714{
1715 puts("Available commands:");
1716 puts(
1717" ? | h - show help n [part] - set mount point\n"
1718" A - auto partition all space p [unit] - print partitions\n"
1719" a [part] - add partition q - quit & save changes\n"
1720" b - set OpenBSD boundaries R [part] - resize auto allocated partition\n"
1721" c [part] - change partition size r - display free space\n"
1722" D - reset label to default s [path] - save label to file\n"
1723" d [part] - delete partition U - undo all changes\n"
1724" e - edit drive parameters u - undo last change\n"
1725" g [d|u] - [d]isk or [u]ser geometry w - write label to disk\n"
1726" i - modify disklabel UID X - toggle expert mode\n"
1727" l [unit] - print disk label header x - exit & lose changes\n"
1728" M - disklabel(8) man page z - delete all partitions\n"
1729" m [part] - modify partition\n"
1730"\n"
1731"Suffixes can be used to indicate units other than sectors:\n"
1732" 'b' (bytes), 'k' (kilobytes), 'm' (megabytes), 'g' (gigabytes) 't' (terabytes)\n"
1733" 'c' (cylinders), '%' (% of total disk), '&' (% of free space).\n"
1734"Values in non-sector units are truncated to the nearest cylinder boundary.");
1735
1736}
1737
1738void
1739mpcopy(char **to, char **from)
1740{
1741 int i;
1742
1743 for (i = 0; i < MAXPARTITIONS16; i++) {
1744 free(to[i]);
1745 to[i] = NULL((void *)0);
1746 if (from[i] != NULL((void *)0)) {
1747 to[i] = strdup(from[i]);
1748 if (to[i] == NULL((void *)0))
1749 errx(4, "out of memory");
1750 }
1751 }
1752}
1753
1754int
1755mpequal(char **mp1, char **mp2)
1756{
1757 int i;
1758
1759 for (i = 0; i < MAXPARTITIONS16; i++) {
1760 if (mp1[i] == NULL((void *)0) && mp2[i] == NULL((void *)0))
1761 continue;
1762
1763 if ((mp1[i] != NULL((void *)0) && mp2[i] == NULL((void *)0)) ||
1764 (mp1[i] == NULL((void *)0) && mp2[i] != NULL((void *)0)) ||
1765 (strcmp(mp1[i], mp2[i]) != 0))
1766 return (0);
1767 }
1768 return (1);
1769}
1770
1771void
1772mpsave(struct disklabel *lp)
1773{
1774 int i, j;
1775 char bdev[PATH_MAX1024], *p;
1776 struct mountinfo mi[MAXPARTITIONS16];
1777 FILE *fp;
1778 u_int8_t fstype;
1779
1780 if (!fstabfile)
1781 return;
1782
1783 memset(&mi, 0, sizeof(mi));
1784
1785 for (i = 0; i < MAXPARTITIONS16; i++) {
1786 fstype = lp->d_partitions[i].p_fstype;
1787 if (mountpoints[i] != NULL((void *)0) || fstype == FS_SWAP1) {
1788 mi[i].mountpoint = mountpoints[i];
1789 mi[i].partno = i;
1790 }
1791 }
1792
1793 /* Convert specname to bdev */
1794 if (uidflag) {
1795 snprintf(bdev, sizeof(bdev),
1796 "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx.%c",
1797 lab.d_uid[0], lab.d_uid[1], lab.d_uid[2], lab.d_uid[3],
1798 lab.d_uid[4], lab.d_uid[5], lab.d_uid[6], lab.d_uid[7],
1799 specname[strlen(specname)-1]);
1800 } else if (strncmp(_PATH_DEV"/dev/", specname, sizeof(_PATH_DEV"/dev/") - 1) == 0 &&
1801 specname[sizeof(_PATH_DEV"/dev/") - 1] == 'r') {
1802 snprintf(bdev, sizeof(bdev), "%s%s", _PATH_DEV"/dev/",
1803 &specname[sizeof(_PATH_DEV"/dev/")]);
1804 } else {
1805 if ((p = strrchr(specname, '/')) == NULL((void *)0) || *(++p) != 'r')
1806 return;
1807 *p = '\0';
1808 snprintf(bdev, sizeof(bdev), "%s%s", specname, p + 1);
1809 *p = 'r';
1810 }
1811 bdev[strlen(bdev) - 1] = '\0';
1812
1813 /* Sort mountpoints so we don't try to mount /usr/local before /usr */
1814 qsort((void *)mi, MAXPARTITIONS16, sizeof(struct mountinfo), micmp);
1815
1816 if ((fp = fopen(fstabfile, "w"))) {
1817 for (i = 0; i < MAXPARTITIONS16; i++) {
1818 j = mi[i].partno;
1819 fstype = lp->d_partitions[j].p_fstype;
1820 if (fstype == FS_SWAP1) {
1821 fprintf(fp, "%s%c none swap sw\n", bdev, 'a'+j);
1822 } else if (mi[i].mountpoint) {
1823 fprintf(fp, "%s%c %s %s rw 1 %d\n", bdev,
1824 'a' + j, mi[i].mountpoint,
1825 fstypesnames[fstype], j == 0 ? 1 : 2);
1826 }
1827 }
1828 fclose(fp);
1829 }
1830}
1831
1832void
1833mpfree(char **mp)
1834{
1835 int part;
1836
1837 if (mp == NULL((void *)0))
1838 return;
1839
1840 for (part = 0; part < MAXPARTITIONS16; part++)
1841 free(mp[part]);
1842
1843 free(mp);
1844}
1845
1846int
1847get_offset(struct disklabel *lp, int partno)
1848{
1849 struct partition opp, *pp = &lp->d_partitions[partno];
1850 u_int64_t ui, offsetalign;
1851 int flags;
1852
1853 flags = DO_CONVERSIONS0x00000001;
1854 ui = getuint64(lp, "offset",
1855 "Starting sector for this partition.",
1856 DL_GETPOFFSET(pp)(((u_int64_t)(pp)->p_offseth << 32) + (pp)->p_offset
)
,
1857 DL_GETPOFFSET(pp)(((u_int64_t)(pp)->p_offseth << 32) + (pp)->p_offset
)
, &flags);
1858
1859 if (ui == CMD_ABORTED((9223372036854775807LL*2ULL+1ULL) - 1) || ui == CMD_BADVALUE((9223372036854775807LL*2ULL+1ULL)))
1860 return (1);
1861#ifdef SUN_AAT0
1862 if (partno == 0 && ui != 0) {
1863 fprintf(stderr(&__sF[2]), "This architecture requires that "
1864 "partition 'a' start at sector 0.\n");
1865 return (1);
1866 }
1867#endif
1868 opp = *pp;
1869 DL_SETPOFFSET(pp, ui)do { u_int64_t __x = (ui); (pp)->p_offseth = __x >> 32
; (pp)->p_offset = __x; } while (0)
;
1870 offsetalign = 1;
1871 if ((flags & DO_ROUNDING0x00000002) != 0 && pp->p_fstype == FS_BSDFFS7)
1872 offsetalign = lp->d_secpercyl;
1873
1874 if (alignpartition(lp, partno, offsetalign, 1, ROUND_OFFSET_UP0x00000001) == 1) {
1875 *pp = opp;
1876 return (1);
1877 }
1878
1879 if (expert == 1 && quiet == 0 && ui != DL_GETPOFFSET(pp)(((u_int64_t)(pp)->p_offseth << 32) + (pp)->p_offset
)
)
1880 printf("offset rounded to sector %llu\n", DL_GETPOFFSET(pp)(((u_int64_t)(pp)->p_offseth << 32) + (pp)->p_offset
)
);
1881
1882 return (0);
1883}
1884
1885int
1886get_size(struct disklabel *lp, int partno)
1887{
1888 struct partition opp, *pp = &lp->d_partitions[partno];
1889 u_int64_t maxsize, ui, sizealign;
1890 int flags;
1891
1892 maxsize = max_partition_size(lp, partno);
1893 flags = DO_CONVERSIONS0x00000001;
1894 ui = getuint64(lp, "size", "Size of the partition. "
1895 "You may also say +/- amount for a relative change.",
1896 DL_GETPSIZE(pp)(((u_int64_t)(pp)->p_sizeh << 32) + (pp)->p_size), maxsize, &flags);
1897
1898 if (ui == CMD_ABORTED((9223372036854775807LL*2ULL+1ULL) - 1) || ui == CMD_BADVALUE((9223372036854775807LL*2ULL+1ULL)))
1899 return (1);
1900
1901 opp = *pp;
1902 DL_SETPSIZE(pp, ui)do { u_int64_t __x = (ui); (pp)->p_sizeh = __x >> 32
; (pp)->p_size = __x; } while (0)
;
1903 sizealign = 1;
1904 if ((flags & DO_ROUNDING0x00000002) != 0 && (pp->p_fstype == FS_SWAP1 ||
1905 pp->p_fstype == FS_BSDFFS7))
1906 sizealign = lp->d_secpercyl;
1907
1908 if (alignpartition(lp, partno, 1, sizealign, ROUND_SIZE_UP0x00000004) == 1) {
1909 *pp = opp;
1910 return (1);
1911 }
1912
1913 if (expert == 1 && quiet == 0 && ui != DL_GETPSIZE(pp)(((u_int64_t)(pp)->p_sizeh << 32) + (pp)->p_size))
1914 printf("size rounded to %llu sectors\n", DL_GETPSIZE(pp)(((u_int64_t)(pp)->p_sizeh << 32) + (pp)->p_size));
1915
1916 return (0);
1917}
1918
1919int
1920get_cpg(struct disklabel *lp, int partno)
1921{
1922 u_int64_t ui;
1923 struct partition *pp = &lp->d_partitions[partno];
1924
1925 if (pp->p_fstype != FS_BSDFFS7)
1926 return (0);
1927
1928 if (pp->p_cpg == 0)
1929 pp->p_cpg = 1;
1930
1931 if (expert == 0)
1932 return (0);
1933
1934 for (;;) {
1935 ui = getnumber("cpg", "Size of partition in fs blocks.",
1936 pp->p_cpg, USHRT_MAX(32767 *2 +1));
1937 if (ui == CMD_ABORTED((9223372036854775807LL*2ULL+1ULL) - 1))
1938 return (1);
1939 else if (ui == CMD_BADVALUE((9223372036854775807LL*2ULL+1ULL)))
1940 ; /* Try again. */
1941 else
1942 break;
1943 }
1944 pp->p_cpg = ui;
1945 return (0);
1946}
1947
1948int
1949get_fsize(struct disklabel *lp, int partno)
1950{
1951 struct partition *pp = &lp->d_partitions[partno];
1952 u_int64_t ui, bytes;
1953 u_int32_t frag, fsize;
1954
1955 if (pp->p_fstype != FS_BSDFFS7)
1956 return (0);
1957
1958 fsize = DISKLABELV1_FFS_FSIZE(pp->p_fragblock)(((pp->p_fragblock) == 0 ? 0 : (1 << (((pp->p_fragblock
) & 0x07) - 1))) == 0 ? 0 : (((pp->p_fragblock) == 0 ?
0 : (1 << (((pp->p_fragblock) >> 3) + 12))) /
((pp->p_fragblock) == 0 ? 0 : (1 << (((pp->p_fragblock
) & 0x07) - 1)))))
;
1959 frag = DISKLABELV1_FFS_FRAG(pp->p_fragblock)((pp->p_fragblock) == 0 ? 0 : (1 << (((pp->p_fragblock
) & 0x07) - 1)))
;
1960 if (fsize == 0) {
1961 fsize = 2048;
1962 frag = 8;
1963 bytes = DL_GETPSIZE(pp)(((u_int64_t)(pp)->p_sizeh << 32) + (pp)->p_size) * lp->d_secsize;
1964 if (bytes > 128ULL * 1024 * 1024 * 1024)
1965 fsize *= 2;
1966 if (bytes > 512ULL * 1024 * 1024 * 1024)
1967 fsize *= 2;
1968 if (fsize < lp->d_secsize)
1969 fsize = lp->d_secsize;
1970 if (fsize > MAXBSIZE(64 * 1024) / frag)
1971 fsize = MAXBSIZE(64 * 1024) / frag;
1972 pp->p_fragblock = DISKLABELV1_FFS_FRAGBLOCK(fsize, frag)((fsize) * (frag) == 0 ? 0 : (((ffs((fsize) * (frag)) - 13) <<
3) | (ffs(frag))))
;
1973 }
1974
1975 if (expert == 0)
1976 return (0);
1977
1978 for (;;) {
1979 ui = getnumber("fragment size",
1980 "Size of ffs block fragments. A multiple of the disk "
1981 "sector-size.", fsize, UINT32_MAX0xffffffffU);
1982 if (ui == CMD_ABORTED((9223372036854775807LL*2ULL+1ULL) - 1))
1983 return (1);
1984 else if (ui == CMD_BADVALUE((9223372036854775807LL*2ULL+1ULL)))
1985 ; /* Try again. */
1986 else if (ui < lp->d_secsize || (ui % lp->d_secsize) != 0)
1987 fprintf(stderr(&__sF[2]), "Error: fragment size must be a "
1988 "multiple of the disk sector size (%d)\n",
1989 lp->d_secsize);
1990 else
1991 break;
1992 }
1993 if (ui == 0)
1994 puts("Zero fragment size implies zero block size");
1995 pp->p_fragblock = DISKLABELV1_FFS_FRAGBLOCK(ui, frag)((ui) * (frag) == 0 ? 0 : (((ffs((ui) * (frag)) - 13) <<
3) | (ffs(frag))))
;
1996 return (0);
1997}
1998
1999int
2000get_bsize(struct disklabel *lp, int partno)
2001{
2002 u_int64_t ui, frag, fsize;
2003 struct partition opp, *pp = &lp->d_partitions[partno];
2004 u_int64_t offsetalign, sizealign;
2005 char *p;
2006
2007 if (pp->p_fstype
49.1
Field 'p_fstype' is equal to FS_BSDFFS
!= FS_BSDFFS7)
50
Taking false branch
2008 return (0);
2009
2010 /* Avoid dividing by zero... */
2011 if (pp->p_fragblock == 0)
51
Assuming field 'p_fragblock' is not equal to 0
52
Taking false branch
2012 return (1);
2013
2014 opp = *pp;
2015 if (expert
52.1
'expert' is not equal to 0
== 0)
53
Taking false branch
2016 goto align;
2017
2018 fsize = DISKLABELV1_FFS_FSIZE(pp->p_fragblock)(((pp->p_fragblock) == 0 ? 0 : (1 << (((pp->p_fragblock
) & 0x07) - 1))) == 0 ? 0 : (((pp->p_fragblock) == 0 ?
0 : (1 << (((pp->p_fragblock) >> 3) + 12))) /
((pp->p_fragblock) == 0 ? 0 : (1 << (((pp->p_fragblock
) & 0x07) - 1)))))
;
54
'?' condition is false
55
Assuming the condition is false
56
'?' condition is false
57
'?' condition is false
58
'?' condition is false
2019 frag = DISKLABELV1_FFS_FRAG(pp->p_fragblock)((pp->p_fragblock) == 0 ? 0 : (1 << (((pp->p_fragblock
) & 0x07) - 1)))
;
59
'?' condition is false
2020
2021 for (;;) {
60
Loop condition is true. Entering loop body
2022 ui = getnumber("block size",
2023 "Size of ffs blocks. 1, 2, 4 or 8 times ffs fragment size.",
2024 fsize * frag, UINT32_MAX0xffffffffU);
2025
2026 /* sanity checks */
2027 if (ui == CMD_ABORTED((9223372036854775807LL*2ULL+1ULL) - 1))
61
Assuming the condition is false
62
Taking false branch
2028 return (1);
2029 else if (ui == CMD_BADVALUE((9223372036854775807LL*2ULL+1ULL)))
63
Assuming the condition is false
64
Taking false branch
2030 ; /* Try again. */
2031 else if (ui < getpagesize())
65
Assuming the condition is false
66
Taking false branch
2032 fprintf(stderr(&__sF[2]),
2033 "Error: block size must be at least as big "
2034 "as page size (%d).\n", getpagesize());
2035 else if (ui < fsize || (fsize != ui && fsize * 2 != ui &&
67
Assuming 'ui' is >= 'fsize'
68
Assuming 'fsize' is equal to 'ui'
2036 fsize * 4 != ui && fsize * 8 != ui))
2037 fprintf(stderr(&__sF[2]), "Error: block size must be 1, 2, 4 or "
2038 "8 times fragment size (%llu).\n",
2039 (unsigned long long) fsize);
2040 else
2041 break;
69
Execution continues on line 2043
2042 }
2043 frag = ui / fsize;
2044 pp->p_fragblock = DISKLABELV1_FFS_FRAGBLOCK(fsize, frag)((fsize) * (frag) == 0 ? 0 : (((ffs((fsize) * (frag)) - 13) <<
3) | (ffs(frag))))
;
70
Assuming the condition is false
71
'?' condition is false
2045
2046#ifdef SUN_CYLCHECK
2047 return (0);
2048#endif
2049 p = getstring("Align partition to block size",
2050 "Round the partition offset and size to multiples of bsize?", "y");
2051 if (*p == 'n' || *p == 'N')
72
Assuming the condition is false
73
Assuming the condition is false
74
Taking false branch
2052 return (0);
2053
2054align:
2055#ifdef SUN_CYLCHECK
2056 return (0);
2057#endif
2058 sizealign = (DISKLABELV1_FFS_FRAG(pp->p_fragblock)((pp->p_fragblock) == 0 ? 0 : (1 << (((pp->p_fragblock
) & 0x07) - 1)))
*
75
Assuming field 'p_fragblock' is not equal to 0
76
'?' condition is false
80
The value 0 is assigned to 'sizealign'
2059 DISKLABELV1_FFS_FSIZE(pp->p_fragblock)(((pp->p_fragblock) == 0 ? 0 : (1 << (((pp->p_fragblock
) & 0x07) - 1))) == 0 ? 0 : (((pp->p_fragblock) == 0 ?
0 : (1 << (((pp->p_fragblock) >> 3) + 12))) /
((pp->p_fragblock) == 0 ? 0 : (1 << (((pp->p_fragblock
) & 0x07) - 1)))))
) / lp->d_secsize
;
77
'?' condition is false
78
Assuming the condition is true
79
'?' condition is true
2060 offsetalign = 1;
2061 if (DL_GETPOFFSET(pp)(((u_int64_t)(pp)->p_offseth << 32) + (pp)->p_offset
)
!= starting_sector
)
81
Assuming the condition is true
82
Taking true branch
2062 offsetalign = sizealign;
83
The value 0 is assigned to 'offsetalign'
2063
2064 if (alignpartition(lp, partno, offsetalign, sizealign, ROUND_OFFSET_UP0x00000001 |
84
Passing the value 0 via 3rd parameter 'startalign'
85
Calling 'alignpartition'
2065 ROUND_SIZE_DOWN0x00000008 | ROUND_SIZE_OVERLAP0x00000010) == 1) {
2066 *pp = opp;
2067 return (1);
2068 }
2069
2070 if (expert == 1 && quiet == 0 &&
2071 DL_GETPOFFSET(&opp)(((u_int64_t)(&opp)->p_offseth << 32) + (&opp
)->p_offset)
!= DL_GETPOFFSET(pp)(((u_int64_t)(pp)->p_offseth << 32) + (pp)->p_offset
)
)
2072 printf("offset rounded to sector %llu\n", DL_GETPOFFSET(pp)(((u_int64_t)(pp)->p_offseth << 32) + (pp)->p_offset
)
);
2073 if (expert == 1 && quiet == 0 && DL_GETPSIZE(&opp)(((u_int64_t)(&opp)->p_sizeh << 32) + (&opp)
->p_size)
!= DL_GETPSIZE(pp)(((u_int64_t)(pp)->p_sizeh << 32) + (pp)->p_size))
2074 printf("size rounded to %llu sectors\n", DL_GETPSIZE(pp)(((u_int64_t)(pp)->p_sizeh << 32) + (pp)->p_size));
2075
2076 return (0);
2077}
2078
2079int
2080get_fstype(struct disklabel *lp, int partno)
2081{
2082 char *p;
2083 u_int64_t ui;
2084 struct partition *pp = &lp->d_partitions[partno];
2085
2086 if (pp->p_fstype < FSMAXTYPES(sizeof(fstypenames) / sizeof(fstypenames[0]) - 1)) {
2087 p = getstring("FS type",
2088 "Filesystem type (usually 4.2BSD or swap)",
2089 fstypenames[pp->p_fstype]);
2090 if (p == NULL((void *)0)) {
2091 return (1);
2092 }
2093 for (ui = 0; ui < FSMAXTYPES(sizeof(fstypenames) / sizeof(fstypenames[0]) - 1); ui++) {
2094 if (!strcasecmp(p, fstypenames[ui])) {
2095 pp->p_fstype = ui;
2096 break;
2097 }
2098 }
2099 if (ui >= FSMAXTYPES(sizeof(fstypenames) / sizeof(fstypenames[0]) - 1)) {
2100 printf("Unrecognized filesystem type '%s', treating "
2101 "as 'unknown'\n", p);
2102 pp->p_fstype = FS_OTHER10;
2103 }
2104 } else {
2105 for (;;) {
2106 ui = getnumber("FS type (decimal)",
2107 "Filesystem type as a decimal number; usually 7 "
2108 "(4.2BSD) or 1 (swap).",
2109 pp->p_fstype, UINT8_MAX0xff);
2110 if (ui == CMD_ABORTED((9223372036854775807LL*2ULL+1ULL) - 1))
2111 return (1);
2112 else if (ui == CMD_BADVALUE((9223372036854775807LL*2ULL+1ULL)))
2113 ; /* Try again. */
2114 else
2115 break;
2116 }
2117 pp->p_fstype = ui;
2118 }
2119 return (0);
2120}
2121
2122int
2123get_mp(struct disklabel *lp, int partno)
2124{
2125 struct partition *pp = &lp->d_partitions[partno];
2126 char *p;
2127 int i;
2128
2129 if (fstabfile == NULL((void *)0) ||
2130 pp->p_fstype == FS_UNUSED0 ||
2131 pp->p_fstype == FS_SWAP1 ||
2132 pp->p_fstype == FS_BOOT13 ||
2133 pp->p_fstype == FS_OTHER10 ||
2134 pp->p_fstype == FS_RAID19) {
2135 /* No fstabfile, no names. Not all fstypes can be named */
2136 return 0;
2137 }
2138
2139 for (;;) {
2140 p = getstring("mount point",
2141 "Where to mount this filesystem (ie: / /var /usr)",
2142 mountpoints[partno] ? mountpoints[partno] : "none");
2143 if (p == NULL((void *)0))
2144 return (1);
2145 if (strcasecmp(p, "none") == 0) {
2146 free(mountpoints[partno]);
2147 mountpoints[partno] = NULL((void *)0);
2148 break;
2149 }
2150 for (i = 0; i < MAXPARTITIONS16; i++)
2151 if (mountpoints[i] != NULL((void *)0) && i != partno &&
2152 strcmp(p, mountpoints[i]) == 0)
2153 break;
2154 if (i < MAXPARTITIONS16) {
2155 fprintf(stderr(&__sF[2]), "'%c' already being mounted at "
2156 "'%s'\n", 'a'+i, p);
2157 break;
2158 }
2159 if (*p == '/') {
2160 /* XXX - might as well realloc */
2161 free(mountpoints[partno]);
2162 if ((mountpoints[partno] = strdup(p)) == NULL((void *)0))
2163 errx(4, "out of memory");
2164 break;
2165 }
2166 fputs("Mount points must start with '/'\n", stderr(&__sF[2]));
2167 }
2168
2169 return (0);
2170}
2171
2172int
2173micmp(const void *a1, const void *a2)
2174{
2175 struct mountinfo *mi1 = (struct mountinfo *)a1;
2176 struct mountinfo *mi2 = (struct mountinfo *)a2;
2177
2178 /* We want all the NULLs at the end... */
2179 if (mi1->mountpoint == NULL((void *)0) && mi2->mountpoint == NULL((void *)0))
2180 return (0);
2181 else if (mi1->mountpoint == NULL((void *)0))
2182 return (1);
2183 else if (mi2->mountpoint == NULL((void *)0))
2184 return (-1);
2185 else
2186 return (strcmp(mi1->mountpoint, mi2->mountpoint));
2187}
2188
2189void
2190get_geometry(int f, struct disklabel **dgpp)
2191{
2192 struct stat st;
2193 struct disklabel *disk_geop;
2194
2195 if (fstat(f, &st) == -1)
2196 err(4, "Can't stat device");
2197
2198 /* Get disk geometry */
2199 if ((disk_geop = calloc(1, sizeof(struct disklabel))) == NULL((void *)0))
2200 errx(4, "out of memory");
2201 if (ioctl(f, DIOCGPDINFO((unsigned long)0x40000000 | ((sizeof(struct disklabel) &
0x1fff) << 16) | ((('d')) << 8) | ((114)))
, disk_geop) == -1)
2202 err(4, "DIOCGPDINFO");
2203 *dgpp = disk_geop;
2204}
2205
2206void
2207set_geometry(struct disklabel *lp, struct disklabel *dgp,
2208 struct disklabel *ugp, char *p)
2209{
2210 if (p == NULL((void *)0))
2211 p = getstring("[d]isk or [u]ser geometry",
2212 "Enter 'd' to use the geometry based on what the disk "
2213 "itself thinks it is, or 'u' to use the geometry that "
2214 "was found in the label.",
2215 "d");
2216 if (p == NULL((void *)0))
2217 return;
2218 switch (*p) {
2219 case 'd':
2220 case 'D':
2221 if (dgp == NULL((void *)0))
2222 fputs("BIOS geometry not defined.\n", stderr(&__sF[2]));
2223 else {
2224 lp->d_secsize = dgp->d_secsize;
2225 lp->d_nsectors = dgp->d_nsectors;
2226 lp->d_ntracks = dgp->d_ntracks;
2227 lp->d_ncylinders = dgp->d_ncylinders;
2228 lp->d_secpercyl = dgp->d_secpercyl;
2229 DL_SETDSIZE(lp, DL_GETDSIZE(dgp))do { u_int64_t __x = ((((u_int64_t)(dgp)->d_secperunith <<
32) + (dgp)->d_secperunit)); (lp)->d_secperunith = __x
>> 32; (lp)->d_secperunit = __x; } while (0)
;
2230 }
2231 break;
2232 case 'u':
2233 case 'U':
2234 if (ugp == NULL((void *)0))
2235 fputs("BIOS geometry not defined.\n", stderr(&__sF[2]));
2236 else {
2237 lp->d_secsize = ugp->d_secsize;
2238 lp->d_nsectors = ugp->d_nsectors;
2239 lp->d_ntracks = ugp->d_ntracks;
2240 lp->d_ncylinders = ugp->d_ncylinders;
2241 lp->d_secpercyl = ugp->d_secpercyl;
2242 DL_SETDSIZE(lp, DL_GETDSIZE(ugp))do { u_int64_t __x = ((((u_int64_t)(ugp)->d_secperunith <<
32) + (ugp)->d_secperunit)); (lp)->d_secperunith = __x
>> 32; (lp)->d_secperunit = __x; } while (0)
;
2243 if (dgp != NULL((void *)0) && ugp->d_secsize == dgp->d_secsize &&
2244 ugp->d_nsectors == dgp->d_nsectors &&
2245 ugp->d_ntracks == dgp->d_ntracks &&
2246 ugp->d_ncylinders == dgp->d_ncylinders &&
2247 ugp->d_secpercyl == dgp->d_secpercyl &&
2248 DL_GETDSIZE(ugp)(((u_int64_t)(ugp)->d_secperunith << 32) + (ugp)->
d_secperunit)
== DL_GETDSIZE(dgp)(((u_int64_t)(dgp)->d_secperunith << 32) + (dgp)->
d_secperunit)
)
2249 fputs("Note: user geometry is the same as disk "
2250 "geometry.\n", stderr(&__sF[2]));
2251 }
2252 break;
2253 default:
2254 fputs("You must enter either 'd' or 'u'.\n", stderr(&__sF[2]));
2255 break;
2256 }
2257}
2258
2259void
2260zero_partitions(struct disklabel *lp)
2261{
2262 int i;
2263
2264 for (i = 0; i < MAXPARTITIONS16; i++) {
2265 memset(&lp->d_partitions[i], 0, sizeof(struct partition));
2266 free(mountpoints[i]);
2267 mountpoints[i] = NULL((void *)0);
2268 }
2269
2270 DL_SETPSIZE(&lp->d_partitions[RAW_PART], DL_GETDSIZE(lp))do { u_int64_t __x = ((((u_int64_t)(lp)->d_secperunith <<
32) + (lp)->d_secperunit)); (&lp->d_partitions[2])
->p_sizeh = __x >> 32; (&lp->d_partitions[2])
->p_size = __x; } while (0)
;
2271}
2272
2273u_int64_t
2274max_partition_size(struct disklabel *lp, int partno)
2275{
2276 struct partition *pp = &lp->d_partitions[partno];
2277 struct diskchunk *chunks;
2278 u_int64_t maxsize = 0, offset;
2279 int fstype, i;
2280
2281 fstype = pp->p_fstype;
2282 pp->p_fstype = FS_UNUSED0;
2283 chunks = free_chunks(lp);
2284 pp->p_fstype = fstype;
2285
2286 offset = DL_GETPOFFSET(pp)(((u_int64_t)(pp)->p_offseth << 32) + (pp)->p_offset
)
;
2287 for (i = 0; chunks[i].start != 0 || chunks[i].stop != 0; i++) {
2288 if (offset < chunks[i].start || offset >= chunks[i].stop)
2289 continue;
2290 maxsize = chunks[i].stop - offset;
2291 break;
2292 }
2293 return (maxsize);
2294}
2295
2296void
2297psize(u_int64_t sz, char unit, struct disklabel *lp)
2298{
2299 double d = scale(sz, unit, lp);
2300 if (d < 0)
2301 printf("%llu", sz);
2302 else
2303 printf("%.*f%c", unit == 'B' ? 0 : 1, d, unit);
2304}
2305
2306void
2307display_edit(struct disklabel *lp, char unit)
2308{
2309 u_int64_t fr;
2310 int i;
2311
2312 fr = editor_countfree(lp);
2313 unit = canonical_unit(lp, unit);
2314
2315 printf("OpenBSD area: ");
2316 psize(starting_sector, 0, lp);
2317 printf("-");
2318 psize(ending_sector, 0, lp);
2319 printf("; size: ");
2320 psize(ending_sector - starting_sector, unit, lp);
2321 printf("; free: ");
2322 psize(fr, unit, lp);
2323
2324 printf("\n# %16.16s %16.16s fstype [fsize bsize cpg]\n",
2325 "size", "offset");
2326 for (i = 0; i < lp->d_npartitions; i++)
2327 display_partition(stdout(&__sF[1]), lp, i, unit);
2328}
2329
2330void
2331parse_autotable(char *filename)
2332{
2333 FILE *cfile;
2334 size_t linesize = 0;
2335 char *line = NULL((void *)0), *buf, *t;
2336 uint idx = 0, pctsum = 0;
2337 struct space_allocation *sa;
2338
2339 if ((cfile = fopen(filename, "r")) == NULL((void *)0))
2340 err(1, "%s", filename);
2341 if ((alloc_table = calloc(1, sizeof(struct alloc_table))) == NULL((void *)0))
2342 err(1, NULL((void *)0));
2343 alloc_table_nitems = 1;
2344
2345 while (getline(&line, &linesize, cfile) != -1) {
2346 if ((alloc_table[0].table = reallocarray(alloc_table[0].table,
2347 idx + 1, sizeof(*sa))) == NULL((void *)0))
2348 err(1, NULL((void *)0));
2349 sa = &(alloc_table[0].table[idx]);
2350 memset(sa, 0, sizeof(*sa));
2351 idx++;
2352
2353 buf = line;
2354 if ((sa->mp = get_token(&buf)) == NULL((void *)0) ||
2355 (sa->mp[0] != '/' && strcmp(sa->mp, "swap")))
2356 errx(1, "%s: parse error on line %u", filename, idx);
2357 if ((t = get_token(&buf)) == NULL((void *)0) ||
2358 parse_sizerange(t, &sa->minsz, &sa->maxsz) == -1)
2359 errx(1, "%s: parse error on line %u", filename, idx);
2360 if ((t = get_token(&buf)) != NULL((void *)0) &&
2361 parse_pct(t, &sa->rate) == -1)
2362 errx(1, "%s: parse error on line %u", filename, idx);
2363 if (sa->minsz > sa->maxsz)
2364 errx(1, "%s: min size > max size on line %u", filename,
2365 idx);
2366 pctsum += sa->rate;
2367 }
2368 if (pctsum > 100)
2369 errx(1, "%s: sum of extra space allocation > 100%%", filename);
2370 alloc_table[0].sz = idx;
2371 free(line);
2372 fclose(cfile);
2373}
2374
2375char *
2376get_token(char **s)
2377{
2378 char *p, *r;
2379 size_t tlen = 0;
2380
2381 p = *s;
2382 while (**s != '\0' && !isspace((u_char)**s)) {
2383 (*s)++;
2384 tlen++;
2385 }
2386 if (tlen == 0)
2387 return (NULL((void *)0));
2388
2389 /* eat whitespace */
2390 while (isspace((u_char)**s))
2391 (*s)++;
2392
2393 if ((r = strndup(p, tlen)) == NULL((void *)0))
2394 err(1, NULL((void *)0));
2395 return (r);
2396}
2397
2398int
2399apply_unit(double val, u_char unit, u_int64_t *n)
2400{
2401 u_int64_t factor = 1;
2402
2403 switch (tolower(unit)) {
2404 case 't':
2405 factor *= 1024;
2406 /* FALLTHROUGH */
2407 case 'g':
2408 factor *= 1024;
2409 /* FALLTHROUGH */
2410 case 'm':
2411 factor *= 1024;
2412 /* FALLTHROUGH */
2413 case 'k':
2414 factor *= 1024;
2415 break;
2416 default:
2417 return (-1);
2418 }
2419
2420 val *= factor / DEV_BSIZE(1 << 9);
2421 if (val > ULLONG_MAX(9223372036854775807LL*2ULL+1ULL))
2422 return (-1);
2423 *n = val;
2424 return (0);
2425}
2426
2427int
2428parse_sizespec(const char *buf, double *val, char **unit)
2429{
2430 errno(*__errno()) = 0;
2431 *val = strtod(buf, unit);
2432 if (errno(*__errno()) == ERANGE34 || *val < 0 || *val > ULLONG_MAX(9223372036854775807LL*2ULL+1ULL))
2433 return (-1); /* too big/small */
2434 if (*val == 0 && *unit == buf)
2435 return (-1); /* No conversion performed. */
2436 if (*unit != NULL((void *)0) && *unit[0] == '\0')
2437 *unit = NULL((void *)0);
2438 return (0);
2439}
2440
2441int
2442parse_sizerange(char *buf, u_int64_t *min, u_int64_t *max)
2443{
2444 char *p, *unit1 = NULL((void *)0), *unit2 = NULL((void *)0);
2445 double val1 = 0, val2 = 0;
2446
2447 if ((p = strchr(buf, '-')) != NULL((void *)0)) {
2448 p[0] = '\0';
2449 p++;
2450 }
2451 *max = 0;
2452 if (parse_sizespec(buf, &val1, &unit1) == -1)
2453 return (-1);
2454 if (p != NULL((void *)0) && p[0] != '\0') {
2455 if (p[0] == '*')
2456 *max = -1;
2457 else
2458 if (parse_sizespec(p, &val2, &unit2) == -1)
2459 return (-1);
2460 }
2461 if (unit1 == NULL((void *)0) && (unit1 = unit2) == NULL((void *)0))
2462 return (-1);
2463 if (apply_unit(val1, unit1[0], min) == -1)
2464 return (-1);
2465 if (val2 > 0) {
2466 if (apply_unit(val2, unit2[0], max) == -1)
2467 return (-1);
2468 } else
2469 if (*max == 0)
2470 *max = *min;
2471 free(buf);
2472 return (0);
2473}
2474
2475int
2476parse_pct(char *buf, int *n)
2477{
2478 const char *errstr;
2479
2480 if (buf[strlen(buf) - 1] == '%')
2481 buf[strlen(buf) - 1] = '\0';
2482 *n = strtonum(buf, 0, 100, &errstr);
2483 if (errstr) {
2484 warnx("parse percent %s: %s", buf, errstr);
2485 return (-1);
2486 }
2487 free(buf);
2488 return (0);
2489}
2490
2491int
2492alignpartition(struct disklabel *lp, int partno, u_int64_t startalign,
2493 u_int64_t stopalign, int flags)
2494{
2495 struct partition *pp = &lp->d_partitions[partno];
2496 struct diskchunk *chunks;
2497 u_int64_t start, stop, maxstop;
2498 unsigned int i;
2499 u_int8_t fstype;
2500
2501 start = DL_GETPOFFSET(pp)(((u_int64_t)(pp)->p_offseth << 32) + (pp)->p_offset
)
;
2502 if ((flags & ROUND_OFFSET_UP0x00000001) == ROUND_OFFSET_UP0x00000001)
86
Taking true branch
2503 start = ((start + startalign - 1) / startalign) * startalign;
87
Division by zero
2504 else if ((flags & ROUND_OFFSET_DOWN0x00000002) == ROUND_OFFSET_DOWN0x00000002)
2505 start = (start / startalign) * startalign;
2506
2507 /* Find the chunk that contains 'start'. */
2508 fstype = pp->p_fstype;
2509 pp->p_fstype = FS_UNUSED0;
2510 chunks = free_chunks(lp);
2511 pp->p_fstype = fstype;
2512 for (i = 0; chunks[i].start != 0 || chunks[i].stop != 0; i++) {
2513 if (start >= chunks[i].start && start < chunks[i].stop)
2514 break;
2515 }
2516 if (chunks[i].stop == 0) {
2517 fprintf(stderr(&__sF[2]), "'%c' aligned offset %llu lies outside "
2518 "the OpenBSD bounds or inside another partition\n",
2519 'a' + partno, start);
2520 return (1);
2521 }
2522
2523 /* Calculate the new 'stop' sector, the sector after the partition. */
2524 if ((flags & ROUND_SIZE_OVERLAP0x00000010) == 0)
2525 maxstop = (chunks[i].stop / stopalign) * stopalign;
2526 else
2527 maxstop = (ending_sector / stopalign) * stopalign;
2528
2529 stop = DL_GETPOFFSET(pp)(((u_int64_t)(pp)->p_offseth << 32) + (pp)->p_offset
)
+ DL_GETPSIZE(pp)(((u_int64_t)(pp)->p_sizeh << 32) + (pp)->p_size);
2530 if ((flags & ROUND_SIZE_UP0x00000004) == ROUND_SIZE_UP0x00000004)
2531 stop = ((stop + stopalign - 1) / stopalign) * stopalign;
2532 else if ((flags & ROUND_SIZE_DOWN0x00000008) == ROUND_SIZE_DOWN0x00000008)
2533 stop = (stop / stopalign) * stopalign;
2534 if (stop > maxstop)
2535 stop = maxstop;
2536
2537 if (stop <= start) {
2538 fprintf(stderr(&__sF[2]), "not enough space\n");
2539 return (1);
2540 }
2541
2542 if (start != DL_GETPOFFSET(pp)(((u_int64_t)(pp)->p_offseth << 32) + (pp)->p_offset
)
)
2543 DL_SETPOFFSET(pp, start)do { u_int64_t __x = (start); (pp)->p_offseth = __x >>
32; (pp)->p_offset = __x; } while (0)
;
2544 if (stop != DL_GETPOFFSET(pp)(((u_int64_t)(pp)->p_offseth << 32) + (pp)->p_offset
)
+ DL_GETPSIZE(pp)(((u_int64_t)(pp)->p_sizeh << 32) + (pp)->p_size))
2545 DL_SETPSIZE(pp, stop - start)do { u_int64_t __x = (stop - start); (pp)->p_sizeh = __x >>
32; (pp)->p_size = __x; } while (0)
;
2546
2547 return (0);
2548}