1*55403f76Smillert /* $OpenBSD: editor.c,v 1.34 1998/04/14 20:02:48 millert Exp $ */ 26fe57b42Smillert 36fe57b42Smillert /* 46fe57b42Smillert * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com> 56fe57b42Smillert * All rights reserved. 66fe57b42Smillert * 76fe57b42Smillert * Redistribution and use in source and binary forms, with or without 86fe57b42Smillert * modification, are permitted provided that the following conditions 96fe57b42Smillert * are met: 106fe57b42Smillert * 1. Redistributions of source code must retain the above copyright 116fe57b42Smillert * notice, this list of conditions and the following disclaimer. 126fe57b42Smillert * 2. Redistributions in binary form must reproduce the above copyright 136fe57b42Smillert * notice, this list of conditions and the following disclaimer in the 146fe57b42Smillert * documentation and/or other materials provided with the distribution. 156fe57b42Smillert * 3. All advertising materials mentioning features or use of this software 166fe57b42Smillert * must display the following acknowledgement: 176fe57b42Smillert * This product includes software developed by Todd C. Miller. 186fe57b42Smillert * 4. The name of the author may not be used to endorse or promote products 196fe57b42Smillert * derived from this software without specific prior written permission. 206fe57b42Smillert * 216fe57b42Smillert * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 226fe57b42Smillert * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 236fe57b42Smillert * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 246fe57b42Smillert * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 256fe57b42Smillert * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 266fe57b42Smillert * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 276fe57b42Smillert * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 286fe57b42Smillert * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 296fe57b42Smillert * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 306fe57b42Smillert * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 316fe57b42Smillert */ 326fe57b42Smillert 336fe57b42Smillert #ifndef lint 34*55403f76Smillert static char rcsid[] = "$OpenBSD: editor.c,v 1.34 1998/04/14 20:02:48 millert Exp $"; 356fe57b42Smillert #endif /* not lint */ 366fe57b42Smillert 376fe57b42Smillert #include <sys/types.h> 386fe57b42Smillert #include <sys/param.h> 396fe57b42Smillert #define DKTYPENAMES 406fe57b42Smillert #include <sys/disklabel.h> 416fe57b42Smillert 426fe57b42Smillert #include <ufs/ffs/fs.h> 436fe57b42Smillert 446fe57b42Smillert #include <ctype.h> 456fe57b42Smillert #include <err.h> 466fe57b42Smillert #include <errno.h> 476fe57b42Smillert #include <string.h> 486fe57b42Smillert #include <stdio.h> 496fe57b42Smillert #include <stdlib.h> 506fe57b42Smillert #include <unistd.h> 516fe57b42Smillert 524793b14cSmillert #include "pathnames.h" 534793b14cSmillert 546fe57b42Smillert /* flags for getuint() */ 556fe57b42Smillert #define DO_CONVERSIONS 0x00000001 566fe57b42Smillert #define DO_ROUNDING 0x00000002 576fe57b42Smillert 58f98aebd4Smillert #ifndef NUMBOOT 59f98aebd4Smillert #define NUMBOOT 0 60f98aebd4Smillert #endif 61f98aebd4Smillert 6296a888c6Smillert /* structure to describe a portion of a disk */ 6396a888c6Smillert struct diskchunk { 6496a888c6Smillert u_int32_t start; 6596a888c6Smillert u_int32_t stop; 6696a888c6Smillert }; 6796a888c6Smillert 686fe57b42Smillert void edit_parms __P((struct disklabel *, u_int32_t *)); 696fe57b42Smillert int editor __P((struct disklabel *, int)); 706fe57b42Smillert void editor_add __P((struct disklabel *, u_int32_t *, char *)); 716fe57b42Smillert void editor_modify __P((struct disklabel *, u_int32_t *, char *)); 726fe57b42Smillert void editor_delete __P((struct disklabel *, u_int32_t *, char *)); 736fe57b42Smillert void editor_display __P((struct disklabel *, u_int32_t *, char)); 746fe57b42Smillert void editor_change __P((struct disklabel *, u_int32_t *, char *)); 75c0bdc608Smillert void editor_countfree __P((struct disklabel *, u_int32_t *)); 766fe57b42Smillert char *getstring __P((struct disklabel *, char *, char *, char *)); 776fe57b42Smillert u_int32_t getuint __P((struct disklabel *, int, char *, char *, u_int32_t, u_int32_t, int)); 786fe57b42Smillert int has_overlap __P((struct disklabel *, u_int32_t *, int)); 796fe57b42Smillert void make_contiguous __P((struct disklabel *)); 8096a888c6Smillert u_int32_t next_offset __P((struct disklabel *, struct partition *)); 816fe57b42Smillert int partition_cmp __P((const void *, const void *)); 82a7e61405Smillert struct partition **sort_partitions __P((struct disklabel *, u_int16_t *)); 830f820bbbSmillert void getdisktype __P((struct disklabel *, char *)); 8496a888c6Smillert void find_bounds __P((struct disklabel *)); 85e8e8bdb7Sart void set_bounds __P((struct disklabel *, u_int32_t *)); 8696a888c6Smillert struct diskchunk *free_chunks __P((struct disklabel *)); 8796a888c6Smillert 8896a888c6Smillert static u_int32_t starting_sector; 8996a888c6Smillert static u_int32_t ending_sector; 906fe57b42Smillert 916fe57b42Smillert /* from disklabel.c */ 926fe57b42Smillert int checklabel __P((struct disklabel *)); 936fe57b42Smillert void display __P((FILE *, struct disklabel *)); 94af98caf3Sderaadt void display_partition __P((FILE *, struct disklabel *, int, char, int)); 95af98caf3Sderaadt int width_partition __P((struct disklabel *, int)); 96af98caf3Sderaadt 976fe57b42Smillert struct disklabel *readlabel __P((int)); 986fe57b42Smillert struct disklabel *makebootarea __P((char *, struct disklabel *, int)); 996fe57b42Smillert int writelabel __P((int, char *, struct disklabel *)); 1006fe57b42Smillert extern char *bootarea, *specname; 10169220492Smillert extern int donothing; 1024793b14cSmillert #ifdef DOSLABEL 1034793b14cSmillert struct dos_partition *dosdp; /* DOS partition, if found */ 1044793b14cSmillert #endif 1056fe57b42Smillert 1066fe57b42Smillert /* 1076fe57b42Smillert * Simple partition editor. Primarily intended for new labels. 1086fe57b42Smillert */ 1096fe57b42Smillert int 1106fe57b42Smillert editor(lp, f) 1116fe57b42Smillert struct disklabel *lp; 1126fe57b42Smillert int f; 1136fe57b42Smillert { 1146fe57b42Smillert struct disklabel lastlabel, tmplabel, label = *lp; 11596a888c6Smillert struct partition *pp; 11696a888c6Smillert u_int32_t freesectors; 1176fe57b42Smillert FILE *fp; 1186fe57b42Smillert char buf[BUFSIZ], *cmd, *arg; 1196fe57b42Smillert 12096a888c6Smillert /* Don't allow disk type of "unknown" */ 12196a888c6Smillert getdisktype(&label, "You need to specify a disk type for this disk."); 1226fe57b42Smillert 12396a888c6Smillert /* How big is the OpenBSD portion of the disk? */ 12496a888c6Smillert find_bounds(&label); 12596a888c6Smillert 12696a888c6Smillert /* Set freesectors based on bounds and initial label */ 127c0bdc608Smillert editor_countfree(&label, &freesectors); 12896a888c6Smillert 12996a888c6Smillert /* Make sure there is no partition overlap. */ 13096a888c6Smillert if (has_overlap(&label, &freesectors, 1)) 1316fe57b42Smillert errx(1, "can't run when there is partition overlap."); 1326fe57b42Smillert 13396a888c6Smillert /* If we don't have a 'c' partition, create one. */ 13496a888c6Smillert pp = &label.d_partitions[2]; 13596a888c6Smillert if (label.d_npartitions < 3 || pp->p_size == 0) { 13696a888c6Smillert puts("No 'c' partition found, adding one that spans the disk."); 13796a888c6Smillert if (label.d_npartitions < 3) 13896a888c6Smillert label.d_npartitions = 3; 13996a888c6Smillert pp->p_offset = 0; 14096a888c6Smillert pp->p_size = label.d_secperunit; 14196a888c6Smillert pp->p_fstype = FS_UNUSED; 14296a888c6Smillert pp->p_fsize = pp->p_frag = pp->p_cpg = 0; 14396a888c6Smillert } 1440f820bbbSmillert 1456fe57b42Smillert #ifdef CYLCHECK 1466fe57b42Smillert puts("This platform requires that partition offsets/sizes be on cylinder boundaries.\nPartition offsets/sizes will be rounded to the nearest cylinder automatically."); 1476fe57b42Smillert #endif 1486fe57b42Smillert 149f98aebd4Smillert #if defined(OLD_SCSI) 150f98aebd4Smillert /* Some ports use the old scsi system that doesn't get the geom right */ 151*55403f76Smillert if (strcmp(label.d_packname, "fictitious") == 0) 152f98aebd4Smillert puts("Warning, driver-generated label. Disk parameters may be " 153f98aebd4Smillert "incorrect."); 154f98aebd4Smillert #endif 155*55403f76Smillert /* Set d_bbsize and d_sbsize as neccesary */ 156*55403f76Smillert if (strcmp(label.d_packname, "fictitious") == 0) { 157*55403f76Smillert if (label.d_bbsize == 0) 158*55403f76Smillert label.d_bbsize = BBSIZE; 159*55403f76Smillert if (label.d_sbsize == 0) 160*55403f76Smillert label.d_sbsize = SBSIZE; 161*55403f76Smillert } 162f98aebd4Smillert 16396a888c6Smillert puts("\nInitial label editor (enter '?' for help at any prompt)"); 1646fe57b42Smillert lastlabel = label; 1656fe57b42Smillert for (;;) { 1666fe57b42Smillert fputs("> ", stdout); 1676fe57b42Smillert fflush(stdout); 1686fe57b42Smillert rewind(stdin); 1696e0becc5Smillert if (fgets(buf, sizeof(buf), stdin) == NULL) { 1706e0becc5Smillert putchar('\n'); 1716e0becc5Smillert buf[0] = 'q'; 1726e0becc5Smillert buf[1] = '\0'; 1736e0becc5Smillert } 174260513deSmillert if ((cmd = strtok(buf, " \t\r\n")) == NULL) 175260513deSmillert continue; 176260513deSmillert arg = strtok(NULL, " \t\r\n"); 1776fe57b42Smillert 1786fe57b42Smillert switch (*cmd) { 1796fe57b42Smillert 1806fe57b42Smillert case '?': 181ea37abd3Sderaadt case 'h': 182ea37abd3Sderaadt puts("Available commands:"); 183ea37abd3Sderaadt puts("\tp [unit] - print label."); 1849bb06b6bSderaadt puts("\tM - show entire OpenBSD man page for disklabel."); 1856fe57b42Smillert puts("\te - edit drive parameters."); 1866fe57b42Smillert puts("\ta [part] - add new partition."); 18796a888c6Smillert puts("\tb - set OpenBSD disk boundaries."); 1886fe57b42Smillert puts("\tc [part] - change partition size."); 1896fe57b42Smillert puts("\td [part] - delete partition."); 1906fe57b42Smillert puts("\tm [part] - modify existing partition."); 191c0bdc608Smillert puts("\tr - recalculate free space."); 1926fe57b42Smillert puts("\tu - undo last change."); 1936fe57b42Smillert puts("\ts [path] - save label to file."); 194040947cfSmillert puts("\tw - write label to disk."); 1956fe57b42Smillert puts("\tq - quit and save changes."); 1966fe57b42Smillert puts("\tx - exit without saving changes."); 197ea37abd3Sderaadt puts("\t? - this message."); 19896a888c6Smillert puts("Numeric parameters may use suffixes to indicate units:\n\t'b' for bytes, 'c' for cylinders, 'k' for kilobytes, 'm' for megabytes,\n\t'g' for gigabytes or no suffix for sectors (usually 512 bytes).\n\tNon-sector units will be rounded to the nearest cylinder."); 1996fe57b42Smillert break; 2006fe57b42Smillert 2016fe57b42Smillert case 'a': 2026fe57b42Smillert tmplabel = lastlabel; 2036fe57b42Smillert lastlabel = label; 20496a888c6Smillert editor_add(&label, &freesectors, arg); 20596a888c6Smillert if (memcmp(&label, &lastlabel, sizeof(label)) == 0) 20696a888c6Smillert lastlabel = tmplabel; 20796a888c6Smillert break; 20896a888c6Smillert 20996a888c6Smillert case 'b': 21096a888c6Smillert tmplabel = lastlabel; 21196a888c6Smillert lastlabel = label; 212e8e8bdb7Sart set_bounds(&label, &freesectors); 2136fe57b42Smillert if (memcmp(&label, &lastlabel, sizeof(label)) == 0) 2146fe57b42Smillert lastlabel = tmplabel; 2156fe57b42Smillert break; 2166fe57b42Smillert 2176fe57b42Smillert case 'c': 2186fe57b42Smillert tmplabel = lastlabel; 2196fe57b42Smillert lastlabel = label; 22096a888c6Smillert editor_change(&label, &freesectors, arg); 2216fe57b42Smillert if (memcmp(&label, &lastlabel, sizeof(label)) == 0) 2226fe57b42Smillert lastlabel = tmplabel; 2236fe57b42Smillert break; 2246fe57b42Smillert 2256fe57b42Smillert case 'd': 2266fe57b42Smillert tmplabel = lastlabel; 2276fe57b42Smillert lastlabel = label; 22896a888c6Smillert editor_delete(&label, &freesectors, arg); 2296fe57b42Smillert if (memcmp(&label, &lastlabel, sizeof(label)) == 0) 2306fe57b42Smillert lastlabel = tmplabel; 2316fe57b42Smillert break; 2326fe57b42Smillert 2336fe57b42Smillert case 'm': 2346fe57b42Smillert tmplabel = lastlabel; 2356fe57b42Smillert lastlabel = label; 23696a888c6Smillert editor_modify(&label, &freesectors, arg); 2376fe57b42Smillert if (memcmp(&label, &lastlabel, sizeof(label)) == 0) 2386fe57b42Smillert lastlabel = tmplabel; 2396fe57b42Smillert break; 2406fe57b42Smillert 2416fe57b42Smillert case 'p': 24296a888c6Smillert editor_display(&label, &freesectors, arg ? *arg : 0); 2436fe57b42Smillert break; 2446fe57b42Smillert 2455d12b01bSderaadt case 'M': 2464793b14cSmillert fp = popen(_PATH_LESS, "w"); 2475d12b01bSderaadt if (fp) { 2485d12b01bSderaadt extern char manpage[]; 2495d12b01bSderaadt 2505d12b01bSderaadt (void) fwrite(manpage, strlen(manpage), 1, fp); 2515d12b01bSderaadt pclose(fp); 2525d12b01bSderaadt } 2535d12b01bSderaadt break; 2545d12b01bSderaadt 2556fe57b42Smillert case 'q': 25669220492Smillert if (donothing) { 25769220492Smillert puts("In no change mode, not writing label."); 25869220492Smillert return(1); 25969220492Smillert } 2606fe57b42Smillert if (memcmp(lp, &label, sizeof(label)) == 0) { 2616fe57b42Smillert puts("No changes."); 2626fe57b42Smillert return(1); 2636fe57b42Smillert } 2646fe57b42Smillert do { 2656fe57b42Smillert arg = getstring(lp, "Save changes?", 2666fe57b42Smillert "Save changes you have made to the label?", 2676fe57b42Smillert "n"); 26896a888c6Smillert } while (arg && tolower(*arg) != 'y' && tolower(*arg) != 'n'); 26996a888c6Smillert if (arg && tolower(*arg) == 'y') { 2706fe57b42Smillert *lp = label; 2716fe57b42Smillert if (writelabel(f, bootarea, lp) == 0) 2726fe57b42Smillert return(0); 2736fe57b42Smillert } 2746fe57b42Smillert return(1); 2756fe57b42Smillert /* NOTREACHED */ 2766fe57b42Smillert break; 2776fe57b42Smillert 278c0bdc608Smillert case 'r': 279c0bdc608Smillert /* Recalculate free space */ 280c0bdc608Smillert editor_countfree(&label, &freesectors); 281c0bdc608Smillert puts("Recalculated free space."); 282c0bdc608Smillert break; 283c0bdc608Smillert 2846fe57b42Smillert case 's': 2856fe57b42Smillert if (arg == NULL) { 286260513deSmillert arg = getstring(lp, "Filename", 2876fe57b42Smillert "Name of the file to save label into.", 2886fe57b42Smillert NULL); 28996a888c6Smillert if (arg == NULL && *arg == '\0') 2906fe57b42Smillert break; 2916fe57b42Smillert } 2926fe57b42Smillert if ((fp = fopen(arg, "w")) == NULL) { 2936fe57b42Smillert warn("cannot open %s", arg); 2946fe57b42Smillert } else { 2956fe57b42Smillert display(fp, &label); 2966fe57b42Smillert (void)fclose(fp); 2976fe57b42Smillert } 2986fe57b42Smillert break; 2996fe57b42Smillert 3006fe57b42Smillert case 'u': 3016fe57b42Smillert if (memcmp(&label, &lastlabel, sizeof(label)) == 0) { 3026fe57b42Smillert puts("Nothing to undo!"); 3036fe57b42Smillert } else { 3046fe57b42Smillert tmplabel = label; 3056fe57b42Smillert label = lastlabel; 3066fe57b42Smillert lastlabel = tmplabel; 307c0bdc608Smillert /* Recalculate free space */ 308c0bdc608Smillert editor_countfree(&label, &freesectors); 3096fe57b42Smillert puts("Last change undone."); 3106fe57b42Smillert } 3116fe57b42Smillert break; 3126fe57b42Smillert 313040947cfSmillert case 'w': 314040947cfSmillert if (donothing) 315040947cfSmillert puts("In no change mode, not writing label."); 316040947cfSmillert else if (memcmp(lp, &label, sizeof(label)) == 0) 317040947cfSmillert puts("No changes."); 318040947cfSmillert else if (writelabel(f, bootarea, &label) != 0) 319040947cfSmillert warnx("unable to write label"); 3205af08e9cSmillert else 3215af08e9cSmillert *lp = label; 322040947cfSmillert break; 323040947cfSmillert 3246fe57b42Smillert case 'x': 3256fe57b42Smillert return(1); 3266fe57b42Smillert break; 3276fe57b42Smillert 3286fe57b42Smillert case '\n': 3296fe57b42Smillert break; 3306fe57b42Smillert 3316fe57b42Smillert case 'e': 3326fe57b42Smillert tmplabel = lastlabel; 3336fe57b42Smillert lastlabel = label; 33496a888c6Smillert edit_parms(&label, &freesectors); 3356fe57b42Smillert if (memcmp(&label, &lastlabel, sizeof(label)) == 0) 3366fe57b42Smillert lastlabel = tmplabel; 3376fe57b42Smillert break; 3386fe57b42Smillert 3396fe57b42Smillert default: 3406fe57b42Smillert printf("Unknown option: %c ('?' for help)\n", *cmd); 3416fe57b42Smillert break; 3426fe57b42Smillert } 3436fe57b42Smillert } 3446fe57b42Smillert } 3456fe57b42Smillert 3466fe57b42Smillert /* 3476fe57b42Smillert * Add a new partition. 3486fe57b42Smillert */ 3496fe57b42Smillert void 3506fe57b42Smillert editor_add(lp, freep, p) 3516fe57b42Smillert struct disklabel *lp; 3526fe57b42Smillert u_int32_t *freep; 3536fe57b42Smillert char *p; 3546fe57b42Smillert { 35596a888c6Smillert struct partition *pp; 35696a888c6Smillert struct diskchunk *chunks; 3576fe57b42Smillert char buf[BUFSIZ]; 3586fe57b42Smillert int i, partno; 35996a888c6Smillert u_int32_t ui, old_offset, old_size; 3606fe57b42Smillert 3616fe57b42Smillert /* XXX - prompt user to steal space from another partition instead */ 3626fe57b42Smillert if (*freep == 0) { 3636fe57b42Smillert fputs("No space left, you need to shrink a partition\n", 3646fe57b42Smillert stderr); 3656fe57b42Smillert return; 3666fe57b42Smillert } 3676fe57b42Smillert 3686fe57b42Smillert /* XXX - make more like other editor_* */ 3696fe57b42Smillert if (p != NULL) { 3706fe57b42Smillert partno = p[0] - 'a'; 3716fe57b42Smillert if (partno < 0 || partno >= MAXPARTITIONS) { 3726fe57b42Smillert fprintf(stderr, 3736fe57b42Smillert "Partition must be between 'a' and '%c'.\n", 3746fe57b42Smillert 'a' + MAXPARTITIONS - 1); 3756fe57b42Smillert return; 37696a888c6Smillert } else if (lp->d_partitions[partno].p_fstype != FS_UNUSED && 377f6299b35Sderaadt lp->d_partitions[partno].p_size != 0) { 378f6299b35Sderaadt fprintf(stderr, 379f6299b35Sderaadt "Partition '%c' exists. Delete it first.\n", 380f6299b35Sderaadt p[0]); 381f6299b35Sderaadt return; 3826fe57b42Smillert } 3836fe57b42Smillert } else { 3846fe57b42Smillert /* Find first unused partition that is not 'b' or 'c' */ 3856fe57b42Smillert for (partno = 0; partno < MAXPARTITIONS; partno++, p++) { 3866fe57b42Smillert if (lp->d_partitions[partno].p_size == 0 && 3876fe57b42Smillert partno != 1 && partno != 2) 3886fe57b42Smillert break; 3896fe57b42Smillert } 3906fe57b42Smillert if (partno < MAXPARTITIONS) { 3916fe57b42Smillert buf[0] = partno + 'a'; 3926fe57b42Smillert buf[1] = '\0'; 3936fe57b42Smillert p = &buf[0]; 3946fe57b42Smillert } else 3956fe57b42Smillert p = NULL; 3966fe57b42Smillert for (;;) { 3976fe57b42Smillert p = getstring(lp, "partition", 3986fe57b42Smillert "The letter of the new partition, a - p.", p); 39996a888c6Smillert if (p == NULL) 40096a888c6Smillert return; 4016fe57b42Smillert partno = p[0] - 'a'; 40296a888c6Smillert if (lp->d_partitions[partno].p_fstype != FS_UNUSED && 40396a888c6Smillert lp->d_partitions[partno].p_size != 0) { 40496a888c6Smillert fprintf(stderr, 40596a888c6Smillert "Partition '%c' already exists.\n", p[0]); 40696a888c6Smillert } else if (partno >= 0 && partno < MAXPARTITIONS) 4076fe57b42Smillert break; 4086fe57b42Smillert fprintf(stderr, 4096fe57b42Smillert "Partition must be between 'a' and '%c'.\n", 4106fe57b42Smillert 'a' + MAXPARTITIONS - 1); 4116fe57b42Smillert } 4126fe57b42Smillert } 41396a888c6Smillert 41496a888c6Smillert /* Increase d_npartitions if necesary */ 41596a888c6Smillert if (partno >= lp->d_npartitions) 41696a888c6Smillert lp->d_npartitions = partno + 1; 41796a888c6Smillert 41896a888c6Smillert /* Set defaults */ 4196fe57b42Smillert pp = &lp->d_partitions[partno]; 4206fe57b42Smillert if (partno >= lp->d_npartitions) 4216fe57b42Smillert lp->d_npartitions = partno + 1; 4226fe57b42Smillert memset(pp, 0, sizeof(*pp)); 42396a888c6Smillert pp->p_fstype = partno == 1 ? FS_SWAP : FS_BSDFFS; 4246fe57b42Smillert pp->p_fsize = 1024; 4256fe57b42Smillert pp->p_frag = 8; 4266fe57b42Smillert pp->p_cpg = 16; 42796a888c6Smillert pp->p_size = *freep; 42896a888c6Smillert pp->p_offset = next_offset(lp, pp); /* must be computed last */ 429f98aebd4Smillert #if NUMBOOT == 1 430f98aebd4Smillert /* Don't clobber boot blocks */ 431f98aebd4Smillert if (pp->p_offset == 0) { 4328dddfaa0Smillert pp->p_offset = lp->d_secpercyl; 4338dddfaa0Smillert pp->p_size -= lp->d_secpercyl; 434f98aebd4Smillert } 435f98aebd4Smillert #endif 43696a888c6Smillert old_offset = pp->p_offset; 43796a888c6Smillert old_size = pp->p_size; 43896a888c6Smillert 43996a888c6Smillert getoff1: 44096a888c6Smillert /* Get offset */ 44196a888c6Smillert for (;;) { 44296a888c6Smillert ui = getuint(lp, partno, "offset", 44396a888c6Smillert "Starting sector for this partition.", pp->p_offset, 44496a888c6Smillert pp->p_offset, DO_CONVERSIONS | 44596a888c6Smillert (pp->p_fstype == FS_BSDFFS ? DO_ROUNDING : 0)); 44696a888c6Smillert if (ui == UINT_MAX - 1) { 44796a888c6Smillert fputs("Command aborted\n", stderr); 44896a888c6Smillert pp->p_size = 0; /* effective delete */ 44996a888c6Smillert return; 45096a888c6Smillert } else if (ui == UINT_MAX) 45196a888c6Smillert fputs("Invalid entry\n", stderr); 45296a888c6Smillert else if (ui < starting_sector) 45396a888c6Smillert fprintf(stderr, "The OpenBSD portion of the disk starts" 454f98aebd4Smillert " at sector %u, you tried to add a partition at %u." 455f98aebd4Smillert " You can use the 'b' command to change the size " 456f98aebd4Smillert "of the OpenBSD portion.\n" , starting_sector, ui); 45796a888c6Smillert else if (ui >= ending_sector) 45896a888c6Smillert fprintf(stderr, "The OpenBSD portion of the disk ends " 459f98aebd4Smillert "at sector %u, you tried to add a partition at %u." 460f98aebd4Smillert " You can use the 'b' command to change the size " 461f98aebd4Smillert "of the OpenBSD portion.\n", ending_sector, ui); 46296a888c6Smillert else 46396a888c6Smillert break; 46496a888c6Smillert } 46596a888c6Smillert pp->p_offset = ui; 46696a888c6Smillert 46796a888c6Smillert /* Recompute recommended size based on new offset */ 46896a888c6Smillert ui = pp->p_fstype; 46996a888c6Smillert pp->p_fstype = FS_UNUSED; 47096a888c6Smillert chunks = free_chunks(lp); 47196a888c6Smillert for (i = 0; chunks[i].start != 0 || chunks[i].stop != 0; i++) { 47296a888c6Smillert if (pp->p_offset >= chunks[i].start && 47396a888c6Smillert pp->p_offset < chunks[i].stop) { 47496a888c6Smillert pp->p_size = chunks[i].stop - pp->p_offset; 47596a888c6Smillert break; 47696a888c6Smillert } 47796a888c6Smillert } 47896a888c6Smillert pp->p_fstype = ui; 47996a888c6Smillert 48096a888c6Smillert /* Get size */ 48196a888c6Smillert for (;;) { 48296a888c6Smillert ui = getuint(lp, partno, "size", "Size of the partition.", 48396a888c6Smillert pp->p_size, *freep, DO_CONVERSIONS | 48496a888c6Smillert ((pp->p_fstype == FS_BSDFFS || pp->p_fstype == FS_SWAP) ? 48596a888c6Smillert DO_ROUNDING : 0)); 48696a888c6Smillert if (ui == UINT_MAX - 1) { 48796a888c6Smillert fputs("Command aborted\n", stderr); 48896a888c6Smillert pp->p_size = 0; /* effective delete */ 48996a888c6Smillert return; 49096a888c6Smillert } else if (ui == UINT_MAX) 49196a888c6Smillert fputs("Invalid entry\n", stderr); 49296a888c6Smillert else if (ui > *freep) 49396a888c6Smillert /* XXX - prompt user to steal space from another partition */ 49496a888c6Smillert fprintf(stderr,"Sorry, there are only %u sectors left\n", 49596a888c6Smillert *freep); 49696a888c6Smillert else if (pp->p_offset + ui > ending_sector) 49796a888c6Smillert fprintf(stderr, "The OpenBSD portion of the disk ends " 49896a888c6Smillert "at sector %u, you tried to add a partition ending " 499f98aebd4Smillert "at sector %u. You can use the 'b' command to " 500f98aebd4Smillert "change the size of the OpenBSD portion.\n", 50196a888c6Smillert ending_sector, pp->p_offset + ui); 50296a888c6Smillert else 50396a888c6Smillert break; 50496a888c6Smillert } 50596a888c6Smillert pp->p_size = ui; 50696a888c6Smillert if (pp->p_size == 0) 50796a888c6Smillert return; 50896a888c6Smillert 50996a888c6Smillert /* Check for overlap */ 51096a888c6Smillert if (has_overlap(lp, freep, 0)) { 5114793b14cSmillert printf("\nPlease re-enter an offset and size for partition " 5124793b14cSmillert "%c.\n", 'a' + partno); 51396a888c6Smillert pp->p_offset = old_offset; 51496a888c6Smillert pp->p_size = old_size; 51596a888c6Smillert goto getoff1; /* Yeah, I know... */ 51696a888c6Smillert } 5176fe57b42Smillert 5186fe57b42Smillert /* Get fstype */ 5196fe57b42Smillert if (pp->p_fstype < FSMAXTYPES) { 5206fe57b42Smillert p = getstring(lp, "FS type", 5216fe57b42Smillert "Filesystem type (usually 4.2BSD or swap)", 5226fe57b42Smillert fstypenames[pp->p_fstype]); 52396a888c6Smillert if (p == NULL) { 52496a888c6Smillert fputs("Command aborted\n", stderr); 52596a888c6Smillert pp->p_size = 0; /* effective delete */ 52696a888c6Smillert return; 52796a888c6Smillert } 5286fe57b42Smillert for (i = 0; i < FSMAXTYPES; i++) { 5296fe57b42Smillert if (!strcasecmp(p, fstypenames[i])) { 5306fe57b42Smillert pp->p_fstype = i; 5316fe57b42Smillert break; 5326fe57b42Smillert } 5336fe57b42Smillert } 5346fe57b42Smillert if (i >= FSMAXTYPES) { 5356fe57b42Smillert printf("Unrecognized filesystem type '%s', treating as 'unknown'\n", p); 5366fe57b42Smillert pp->p_fstype = FS_OTHER; 5376fe57b42Smillert } 5386fe57b42Smillert } else { 5396fe57b42Smillert for (;;) { 5406fe57b42Smillert ui = getuint(lp, partno, "FS type (decimal)", 5416fe57b42Smillert "Filesystem type as a decimal number; usually 7 (4.2BSD) or 1 (swap).", 5426fe57b42Smillert pp->p_fstype, pp->p_fstype, 0); 54396a888c6Smillert if (ui == UINT_MAX - 1) { 54496a888c6Smillert fputs("Command aborted\n", stderr); 54596a888c6Smillert pp->p_size = 0; /* effective delete */ 54696a888c6Smillert return; 54796a888c6Smillert } if (ui == UINT_MAX) 5486fe57b42Smillert fputs("Invalid entry\n", stderr); 5496fe57b42Smillert else 5506fe57b42Smillert break; 5516fe57b42Smillert } 5526fe57b42Smillert pp->p_fstype = ui; 5536fe57b42Smillert } 5546fe57b42Smillert 5556fe57b42Smillert if (pp->p_fstype == FS_BSDFFS || pp->p_fstype == FS_UNUSED) { 5566fe57b42Smillert /* get fsize */ 5576fe57b42Smillert for (;;) { 5586fe57b42Smillert ui = getuint(lp, partno, "fragment size", 5596fe57b42Smillert "Size of fs block fragments. Usually 1024 or 512.", 5606fe57b42Smillert pp->p_fsize, pp->p_fsize, 0); 56196a888c6Smillert if (ui == UINT_MAX - 1) { 56296a888c6Smillert fputs("Command aborted\n", stderr); 56396a888c6Smillert pp->p_size = 0; /* effective delete */ 56496a888c6Smillert return; 56596a888c6Smillert } else if (ui == UINT_MAX) 5666fe57b42Smillert fputs("Invalid entry\n", stderr); 5676fe57b42Smillert else 5686fe57b42Smillert break; 5696fe57b42Smillert } 5706fe57b42Smillert pp->p_fsize = ui; 5716fe57b42Smillert if (pp->p_fsize == 0) 5726fe57b42Smillert puts("Zero fragment size implies zero block size"); 5736fe57b42Smillert 5746fe57b42Smillert /* get bsize */ 5756fe57b42Smillert /* XXX - do before frag size? */ 5766fe57b42Smillert for (; pp->p_fsize > 0;) { 5776fe57b42Smillert ui = getuint(lp, partno, "block size", 5786fe57b42Smillert "Size of filesystem blocks. Usually 8192 or 4096.", 5796fe57b42Smillert pp->p_fsize * pp->p_frag, pp->p_fsize * pp->p_frag, 5806fe57b42Smillert 0); 5816fe57b42Smillert 5826fe57b42Smillert /* sanity checks */ 58396a888c6Smillert if (ui == UINT_MAX - 1) { 58496a888c6Smillert fputs("Command aborted\n", stderr); 58596a888c6Smillert pp->p_size = 0; /* effective delete */ 58696a888c6Smillert return; 58796a888c6Smillert } else if (ui == UINT_MAX) 5886fe57b42Smillert fputs("Invalid entry\n", stderr); 5896fe57b42Smillert else if (ui < getpagesize()) 5906fe57b42Smillert fprintf(stderr, 5916fe57b42Smillert "Error: block size must be at least as big " 5926fe57b42Smillert "as page size (%d).\n", getpagesize()); 5936fe57b42Smillert else if (ui % pp->p_fsize != 0) 5946fe57b42Smillert fputs("Error: block size must be a multiple of the fragment size.\n", stderr); 5956fe57b42Smillert else if (ui / pp->p_fsize < 1) 5966fe57b42Smillert fputs("Error: block size must be at least as big as fragment size.\n", stderr); 5976fe57b42Smillert else 5986fe57b42Smillert break; 5996fe57b42Smillert } 6006fe57b42Smillert pp->p_frag = ui / pp->p_fsize; 6016fe57b42Smillert 6026fe57b42Smillert if (pp->p_fstype == FS_BSDFFS) { 6036fe57b42Smillert /* get cpg */ 6046fe57b42Smillert for (;;) { 6056fe57b42Smillert ui = getuint(lp, partno, "cpg", 6066fe57b42Smillert "Number of filesystem cylinders per group. Usually 16 or 8.", 6076fe57b42Smillert pp->p_cpg, pp->p_cpg, 0); 60896a888c6Smillert if (ui == UINT_MAX - 1) { 60996a888c6Smillert fputs("Command aborted\n", stderr); 61096a888c6Smillert pp->p_size = 0; /* effective delete */ 61196a888c6Smillert return; 61296a888c6Smillert } else if (ui == UINT_MAX) 6136fe57b42Smillert fputs("Invalid entry\n", stderr); 6146fe57b42Smillert else 6156fe57b42Smillert break; 6166fe57b42Smillert } 6176fe57b42Smillert pp->p_cpg = ui; 6186fe57b42Smillert } 6196fe57b42Smillert } 62096a888c6Smillert /* Update free sector count and make sure things stay contiguous. */ 6216fe57b42Smillert *freep -= pp->p_size; 62296a888c6Smillert if (pp->p_size + pp->p_offset > ending_sector || 62396a888c6Smillert has_overlap(lp, freep, -1)) 6246fe57b42Smillert make_contiguous(lp); 6256fe57b42Smillert } 6266fe57b42Smillert 6276fe57b42Smillert /* 6286fe57b42Smillert * Change an existing partition. 6296fe57b42Smillert */ 6306fe57b42Smillert void 6316fe57b42Smillert editor_modify(lp, freep, p) 6326fe57b42Smillert struct disklabel *lp; 6336fe57b42Smillert u_int32_t *freep; 6346fe57b42Smillert char *p; 6356fe57b42Smillert { 6366fe57b42Smillert struct partition origpart, *pp; 6376fe57b42Smillert u_int32_t ui; 6386fe57b42Smillert int partno; 6396fe57b42Smillert 6406fe57b42Smillert /* Change which partition? */ 6416fe57b42Smillert if (p == NULL) { 6426fe57b42Smillert p = getstring(lp, "partition to modify", 6436fe57b42Smillert "The letter of the partition to modify, a - p.", NULL); 6446fe57b42Smillert } 64596a888c6Smillert if (p == NULL) { 64696a888c6Smillert fputs("Command aborted\n", stderr); 64796a888c6Smillert return; 64896a888c6Smillert } 6496fe57b42Smillert partno = p[0] - 'a'; 6506fe57b42Smillert pp = &lp->d_partitions[partno]; 6516fe57b42Smillert origpart = lp->d_partitions[partno]; 6526fe57b42Smillert if (partno < 0 || partno >= lp->d_npartitions) { 6536fe57b42Smillert fprintf(stderr, "Partition must be between 'a' and '%c'.\n", 6546fe57b42Smillert 'a' + lp->d_npartitions - 1); 6556fe57b42Smillert return; 6566fe57b42Smillert } else if (partno >= lp->d_npartitions || 6576fe57b42Smillert (pp->p_fstype == FS_UNUSED && pp->p_size == 0)) { 6586fe57b42Smillert fprintf(stderr, "Partition '%c' is not in use.\n", 'a' + partno); 6596fe57b42Smillert return; 6606fe57b42Smillert } 6616fe57b42Smillert 6626fe57b42Smillert /* Get filesystem type */ 6636fe57b42Smillert if (pp->p_fstype < FSMAXTYPES) { 6646fe57b42Smillert p = getstring(lp, "FS type", 6656fe57b42Smillert "Filesystem type (usually 4.2BSD or swap)", 6666fe57b42Smillert fstypenames[pp->p_fstype]); 66796a888c6Smillert if (p == NULL) { 66896a888c6Smillert fputs("Command aborted\n", stderr); 66996a888c6Smillert pp->p_size = 0; /* effective delete */ 67096a888c6Smillert return; 67196a888c6Smillert } 6726fe57b42Smillert for (ui = 0; ui < FSMAXTYPES; ui++) { 6736fe57b42Smillert if (!strcasecmp(p, fstypenames[ui])) { 6746fe57b42Smillert pp->p_fstype = ui; 6756fe57b42Smillert break; 6766fe57b42Smillert } 6776fe57b42Smillert } 6786fe57b42Smillert if (ui >= FSMAXTYPES) { 6796fe57b42Smillert printf("Unrecognized filesystem type '%s', treating as 'unknown'\n", p); 6806fe57b42Smillert pp->p_fstype = FS_OTHER; 6816fe57b42Smillert } 6826fe57b42Smillert } else { 6836fe57b42Smillert for (;;) { 6846fe57b42Smillert ui = getuint(lp, partno, "FS type (decimal)", 6856fe57b42Smillert "Filesystem type as a decimal number; usually 7 (4.2BSD) or 1 (swap).", 6866fe57b42Smillert pp->p_fstype, pp->p_fstype, 0); 68796a888c6Smillert if (ui == UINT_MAX - 1) { 68896a888c6Smillert fputs("Command aborted\n", stderr); 68996a888c6Smillert pp->p_size = 0; /* effective delete */ 69096a888c6Smillert return; 69196a888c6Smillert } else if (ui == UINT_MAX) 6926fe57b42Smillert fputs("Invalid entry\n", stderr); 6936fe57b42Smillert else 6946fe57b42Smillert break; 6956fe57b42Smillert } 6966fe57b42Smillert pp->p_fstype = ui; 6976fe57b42Smillert } 6986fe57b42Smillert 6996fe57b42Smillert /* Did they disable/enable the partition? */ 700229f463eSmillert if ((pp->p_fstype == FS_UNUSED || pp->p_fstype == FS_BOOT) && 701229f463eSmillert origpart.p_fstype != FS_UNUSED && origpart.p_fstype != FS_BOOT) 7026fe57b42Smillert *freep += origpart.p_size; 703229f463eSmillert else if (pp->p_fstype != FS_UNUSED && pp->p_fstype != FS_BOOT && 704229f463eSmillert (origpart.p_fstype == FS_UNUSED || origpart.p_fstype == FS_BOOT)) { 7056fe57b42Smillert if (pp->p_size > *freep) { 7066fe57b42Smillert fprintf(stderr, 70796a888c6Smillert "Warning, need %u sectors but there are only %u " 7086fe57b42Smillert "free. Setting size to %u.\n", pp->p_size, *freep, 7096fe57b42Smillert *freep); 7106fe57b42Smillert pp->p_fstype = *freep; 7116fe57b42Smillert *freep = 0; 7126fe57b42Smillert } else 7136fe57b42Smillert *freep -= pp->p_size; /* have enough space */ 7146fe57b42Smillert } 7156fe57b42Smillert 7166fe57b42Smillert getoff2: 7176fe57b42Smillert /* Get offset */ 7186fe57b42Smillert for (;;) { 7196fe57b42Smillert ui = getuint(lp, partno, "offset", 7206fe57b42Smillert "Starting sector for this partition.", pp->p_offset, 7216fe57b42Smillert pp->p_offset, DO_CONVERSIONS | 7226fe57b42Smillert (pp->p_fstype == FS_BSDFFS ? DO_ROUNDING : 0)); 72396a888c6Smillert if (ui == UINT_MAX - 1) { 72496a888c6Smillert fputs("Command aborted\n", stderr); 72596a888c6Smillert *pp = origpart; /* undo changes */ 72696a888c6Smillert return; 72796a888c6Smillert } else if (ui == UINT_MAX) 7286fe57b42Smillert fputs("Invalid entry\n", stderr); 72996a888c6Smillert else if (partno != 2 && ui + ui < starting_sector) { 73096a888c6Smillert fprintf(stderr, "The OpenBSD portion of the disk starts" 731f98aebd4Smillert " at sector %u, you tried to start at %u." 732f98aebd4Smillert " You can use the 'b' command to change the size " 733f98aebd4Smillert "of the OpenBSD portion.\n", starting_sector, ui); 73496a888c6Smillert } else 7356fe57b42Smillert break; 7366fe57b42Smillert } 7376fe57b42Smillert pp->p_offset = ui; 7386fe57b42Smillert 7396fe57b42Smillert /* Get size */ 7406fe57b42Smillert /* XXX - this loop sucks */ 7416fe57b42Smillert for (;;) { 7426fe57b42Smillert ui = getuint(lp, partno, "size", "Size of the partition.", 7436fe57b42Smillert pp->p_size, *freep, 1); 7446fe57b42Smillert 7456fe57b42Smillert if (ui == pp->p_size) 7466fe57b42Smillert break; /* no change */ 7476fe57b42Smillert 74896a888c6Smillert if (ui == UINT_MAX - 1) { 74996a888c6Smillert fputs("Command aborted\n", stderr); 75096a888c6Smillert *pp = origpart; /* undo changes */ 75196a888c6Smillert return; 75296a888c6Smillert } else if (ui == UINT_MAX) { 7536fe57b42Smillert fputs("Invalid entry\n", stderr); 7546fe57b42Smillert continue; 7556fe57b42Smillert } else if (partno == 2 && ui + pp->p_offset > lp->d_secperunit) { 7566fe57b42Smillert fputs("'c' partition may not be larger than the disk\n", 7576fe57b42Smillert stderr); 7586fe57b42Smillert continue; 7596fe57b42Smillert } 7606fe57b42Smillert 761229f463eSmillert if (pp->p_fstype == FS_UNUSED || pp->p_fstype == FS_BOOT) { 7626fe57b42Smillert pp->p_size = ui; /* don't care what's free */ 7636fe57b42Smillert break; 7646fe57b42Smillert } else { 7656fe57b42Smillert if (ui > pp->p_size + *freep) 7666fe57b42Smillert /* XXX - prompt user to steal space from another partition */ 7676fe57b42Smillert fprintf(stderr, 76896a888c6Smillert "Size may not be larger than %u sectors\n", 7696fe57b42Smillert pp->p_size + *freep); 7706fe57b42Smillert else { 7716fe57b42Smillert *freep += pp->p_size - ui; 7726fe57b42Smillert pp->p_size = ui; 7736fe57b42Smillert break; 7746fe57b42Smillert } 7756fe57b42Smillert } 7766fe57b42Smillert } 777f98aebd4Smillert /* XXX - if (ui % lp->d_secpercyl == 0) make ui + offset on cyl bound */ 778f98aebd4Smillert pp->p_size = ui; 7796fe57b42Smillert if (pp->p_size == 0) 7806fe57b42Smillert return; 7816fe57b42Smillert 7826fe57b42Smillert /* Check for overlap and restore if not resolved */ 7836fe57b42Smillert if (has_overlap(lp, freep, 0)) { 7846fe57b42Smillert puts("\nPlease re-enter an offset and size"); 7856fe57b42Smillert pp->p_offset = origpart.p_offset; 7866fe57b42Smillert pp->p_size = origpart.p_size; 7876fe57b42Smillert goto getoff2; /* Yeah, I know... */ 7886fe57b42Smillert } 7896fe57b42Smillert 7906fe57b42Smillert if (pp->p_fstype == FS_BSDFFS || pp->p_fstype == FS_UNUSED) { 7916fe57b42Smillert /* get fsize */ 7926fe57b42Smillert for (;;) { 7936fe57b42Smillert ui = getuint(lp, partno, "fragment size", 7946fe57b42Smillert "Size of fs block fragments. Usually 1024 or 512.", 7956fe57b42Smillert pp->p_fsize, 1024, 0); 79696a888c6Smillert if (ui == UINT_MAX - 1) { 79796a888c6Smillert fputs("Command aborted\n", stderr); 79896a888c6Smillert *pp = origpart; /* undo changes */ 79996a888c6Smillert return; 80096a888c6Smillert } else if (ui == UINT_MAX) 8016fe57b42Smillert fputs("Invalid entry\n", stderr); 8026fe57b42Smillert else 8036fe57b42Smillert break; 8046fe57b42Smillert } 8056fe57b42Smillert pp->p_fsize = ui; 8066fe57b42Smillert if (pp->p_fsize == 0) 8076fe57b42Smillert puts("Zero fragment size implies zero block size"); 8086fe57b42Smillert 8096fe57b42Smillert /* get bsize */ 8106fe57b42Smillert for (; pp->p_fsize > 0;) { 8116fe57b42Smillert ui = getuint(lp, partno, "block size", 8126fe57b42Smillert "Size of filesystem blocks. Usually 8192 or 4096.", 8136fe57b42Smillert pp->p_fsize * pp->p_frag, pp->p_fsize * pp->p_frag, 8146fe57b42Smillert 0); 8156fe57b42Smillert 8166fe57b42Smillert /* sanity check */ 81796a888c6Smillert if (ui == UINT_MAX - 1) { 81896a888c6Smillert fputs("Command aborted\n", stderr); 81996a888c6Smillert *pp = origpart; /* undo changes */ 82096a888c6Smillert return; 82196a888c6Smillert } else if (ui == UINT_MAX) 8226fe57b42Smillert fputs("Invalid entry\n", stderr); 8236fe57b42Smillert else if (ui % pp->p_fsize != 0) 8246fe57b42Smillert puts("Error: block size must be a multiple of the fragment size."); 8256fe57b42Smillert else if (ui / pp->p_fsize < 1) 8266fe57b42Smillert puts("Error: block size must be at least as big as fragment size."); 8276fe57b42Smillert else { 8286fe57b42Smillert pp->p_frag = ui / pp->p_fsize; 8296fe57b42Smillert break; 8306fe57b42Smillert } 8316fe57b42Smillert } 8326fe57b42Smillert 8336fe57b42Smillert if (pp->p_fstype == FS_BSDFFS) { 8346fe57b42Smillert /* get cpg */ 8356fe57b42Smillert for (;;) { 8366fe57b42Smillert ui = getuint(lp, partno, "cpg", 8376fe57b42Smillert "Number of filesystem cylinders per group." 8386fe57b42Smillert " Usually 16 or 8.", pp->p_cpg, pp->p_cpg, 8396fe57b42Smillert 0); 84096a888c6Smillert if (ui == UINT_MAX - 1) { 84196a888c6Smillert fputs("Command aborted\n", stderr); 84296a888c6Smillert *pp = origpart; /* undo changes */ 84396a888c6Smillert return; 84496a888c6Smillert } else if (ui == UINT_MAX) 8456fe57b42Smillert fputs("Invalid entry\n", stderr); 8466fe57b42Smillert else 8476fe57b42Smillert break; 8486fe57b42Smillert } 8496fe57b42Smillert pp->p_cpg = ui; 8506fe57b42Smillert } 8516fe57b42Smillert } 8526fe57b42Smillert 8536fe57b42Smillert /* Make sure things stay contiguous. */ 85496a888c6Smillert if (pp->p_size + pp->p_offset > ending_sector || 85596a888c6Smillert has_overlap(lp, freep, -1)) 8566fe57b42Smillert make_contiguous(lp); 8576fe57b42Smillert } 8586fe57b42Smillert 8596fe57b42Smillert /* 8606fe57b42Smillert * Delete an existing partition. 8616fe57b42Smillert */ 8626fe57b42Smillert void 8636fe57b42Smillert editor_delete(lp, freep, p) 8646fe57b42Smillert struct disklabel *lp; 8656fe57b42Smillert u_int32_t *freep; 8666fe57b42Smillert char *p; 8676fe57b42Smillert { 8686fe57b42Smillert int c; 8696fe57b42Smillert 8706fe57b42Smillert if (p == NULL) { 8716fe57b42Smillert p = getstring(lp, "partition to delete", 8726fe57b42Smillert "The letter of the partition to delete, a - p.", NULL); 8736fe57b42Smillert } 87496a888c6Smillert if (p == NULL) { 87596a888c6Smillert fputs("Command aborted\n", stderr); 87696a888c6Smillert return; 87796a888c6Smillert } 8786fe57b42Smillert c = p[0] - 'a'; 8796fe57b42Smillert if (c < 0 || c >= lp->d_npartitions) 8806fe57b42Smillert fprintf(stderr, "Partition must be between 'a' and '%c'.\n", 8816fe57b42Smillert 'a' + lp->d_npartitions - 1); 8826fe57b42Smillert else if (c >= lp->d_npartitions || (lp->d_partitions[c].p_fstype == 8836fe57b42Smillert FS_UNUSED && lp->d_partitions[c].p_size == 0)) 8846fe57b42Smillert fprintf(stderr, "Partition '%c' is not in use.\n", 'a' + c); 8856fe57b42Smillert else if (c == 2) 8866fe57b42Smillert fputs("You may not delete the 'c' partition.\n", stderr); 88796a888c6Smillert else if (lp->d_partitions[c].p_offset >= ending_sector || 88896a888c6Smillert lp->d_partitions[c].p_offset < starting_sector) 88996a888c6Smillert fprintf(stderr, "The OpenBSD portion of the disk ends at sector" 89096a888c6Smillert " %u.\nYou can't remove a partition outside the OpenBSD " 891f98aebd4Smillert "part of the disk. You can use the 'b' command to change " 892f98aebd4Smillert "the size of the OpenBSD portion.\n", ending_sector); 8936fe57b42Smillert else { 89496a888c6Smillert /* Update free sector count. */ 8956fe57b42Smillert if (lp->d_partitions[c].p_fstype != FS_UNUSED && 896229f463eSmillert lp->d_partitions[c].p_fstype != FS_BOOT && 8976fe57b42Smillert lp->d_partitions[c].p_size != 0) 8986fe57b42Smillert *freep += lp->d_partitions[c].p_size; 8996fe57b42Smillert 9006fe57b42Smillert /* Really delete it (as opposed to just setting to "unused") */ 9016fe57b42Smillert (void)memset(&lp->d_partitions[c], 0, 9026fe57b42Smillert sizeof(lp->d_partitions[c])); 9036fe57b42Smillert } 9046fe57b42Smillert } 9056fe57b42Smillert 9066fe57b42Smillert /* 9076fe57b42Smillert * Simplified display() for use with the builtin editor. 9086fe57b42Smillert */ 9096fe57b42Smillert void 9106fe57b42Smillert editor_display(lp, freep, unit) 9116fe57b42Smillert struct disklabel *lp; 9126fe57b42Smillert u_int32_t *freep; 9136fe57b42Smillert char unit; 9146fe57b42Smillert { 9156fe57b42Smillert int i; 916af98caf3Sderaadt int width; 9176fe57b42Smillert 9186fe57b42Smillert printf("device: %s\n", specname); 9190f820bbbSmillert printf("type: %s\n", dktypenames[lp->d_type]); 9206fe57b42Smillert printf("disk: %.*s\n", (int)sizeof(lp->d_typename), lp->d_typename); 9216fe57b42Smillert printf("label: %.*s\n", (int)sizeof(lp->d_packname), lp->d_packname); 9226fe57b42Smillert printf("bytes/sector: %ld\n", (long)lp->d_secsize); 9236fe57b42Smillert printf("sectors/track: %ld\n", (long)lp->d_nsectors); 9246fe57b42Smillert printf("tracks/cylinder: %ld\n", (long)lp->d_ntracks); 9256fe57b42Smillert printf("sectors/cylinder: %ld\n", (long)lp->d_secpercyl); 9266fe57b42Smillert printf("cylinders: %ld\n", (long)lp->d_ncylinders); 9276fe57b42Smillert printf("total sectors: %ld\n", (long)lp->d_secperunit); 9286fe57b42Smillert printf("free sectors: %u\n", *freep); 9296fe57b42Smillert printf("rpm: %ld\n", (long)lp->d_rpm); 9306fe57b42Smillert printf("\n%d partitions:\n", lp->d_npartitions); 931af98caf3Sderaadt width = width_partition(lp, unit); 932af98caf3Sderaadt printf("# %*.*s %*.*s fstype [fsize bsize cpg]\n", 933af98caf3Sderaadt width, width, "size", width, width, "offset"); 9346fe57b42Smillert for (i = 0; i < lp->d_npartitions; i++) 935af98caf3Sderaadt display_partition(stdout, lp, i, unit, width); 9366fe57b42Smillert } 9376fe57b42Smillert 9386fe57b42Smillert /* 9396fe57b42Smillert * Find the next reasonable starting offset and returns it. 94096a888c6Smillert * Assumes there is a least one free sector left (returns 0 if not). 9416fe57b42Smillert */ 9426fe57b42Smillert u_int32_t 94396a888c6Smillert next_offset(lp, pp) 9446fe57b42Smillert struct disklabel *lp; 94596a888c6Smillert struct partition *pp; 9466fe57b42Smillert { 947f0b4d0a9Smillert struct partition **spp; 94896a888c6Smillert struct diskchunk *chunks; 949f0b4d0a9Smillert u_int16_t npartitions; 95096a888c6Smillert u_int32_t new_offset, new_size; 95196a888c6Smillert int i, good_offset; 9526fe57b42Smillert 953a7e61405Smillert /* Get a sorted list of the partitions */ 95496a888c6Smillert if ((spp = sort_partitions(lp, &npartitions)) == NULL) 95596a888c6Smillert return(0); 956f0b4d0a9Smillert 95796a888c6Smillert new_offset = starting_sector; 958f0b4d0a9Smillert for (i = 0; i < npartitions; i++ ) { 95996a888c6Smillert /* Skip the partition for which we are finding an offset */ 96096a888c6Smillert if (pp == spp[i]) 96196a888c6Smillert continue; 96296a888c6Smillert 9636fe57b42Smillert /* 9646fe57b42Smillert * Is new_offset inside this partition? If so, 96596a888c6Smillert * make it the next sector after the partition ends. 9666fe57b42Smillert */ 9674793b14cSmillert if (spp[i]->p_offset + spp[i]->p_size < ending_sector && 9684793b14cSmillert ((new_offset >= spp[i]->p_offset && 96996a888c6Smillert new_offset < spp[i]->p_offset + spp[i]->p_size) || 97096a888c6Smillert (new_offset + pp->p_size >= spp[i]->p_offset && new_offset 9714793b14cSmillert + pp->p_size <= spp[i]->p_offset + spp[i]->p_size))) 972f0b4d0a9Smillert new_offset = spp[i]->p_offset + spp[i]->p_size; 9736fe57b42Smillert } 9746fe57b42Smillert 97596a888c6Smillert /* Did we find a suitable offset? */ 97696a888c6Smillert for (good_offset = 1, i = 0; i < npartitions; i++ ) { 97796a888c6Smillert if (new_offset + pp->p_size >= spp[i]->p_offset && 97896a888c6Smillert new_offset + pp->p_size <= spp[i]->p_offset + spp[i]->p_size) { 97996a888c6Smillert /* Nope */ 98096a888c6Smillert good_offset = 0; 98196a888c6Smillert break; 98296a888c6Smillert } 98396a888c6Smillert } 98496a888c6Smillert 98596a888c6Smillert /* Specified size is too big, find something that fits */ 98696a888c6Smillert if (!good_offset) { 98796a888c6Smillert chunks = free_chunks(lp); 98896a888c6Smillert new_size = 0; 98996a888c6Smillert for (i = 0; chunks[i].start != 0 || chunks[i].stop != 0; i++) { 99096a888c6Smillert if (chunks[i].stop - chunks[i].start > new_size) { 99196a888c6Smillert new_size = chunks[i].stop - chunks[i].start; 99296a888c6Smillert new_offset = chunks[i].start; 99396a888c6Smillert } 99496a888c6Smillert } 9954793b14cSmillert /* XXX - should do something intelligent if new_size == 0 */ 99696a888c6Smillert pp->p_size = new_size; 99796a888c6Smillert } 99896a888c6Smillert 999f0b4d0a9Smillert (void)free(spp); 10006fe57b42Smillert return(new_offset); 10016fe57b42Smillert } 10026fe57b42Smillert 10036fe57b42Smillert /* 10046fe57b42Smillert * Change the size of an existing partition. 10056fe57b42Smillert */ 10066fe57b42Smillert void 10076fe57b42Smillert editor_change(lp, freep, p) 10086fe57b42Smillert struct disklabel *lp; 10096fe57b42Smillert u_int32_t *freep; 10106fe57b42Smillert char *p; 10116fe57b42Smillert { 10126fe57b42Smillert int partno; 10136fe57b42Smillert u_int32_t newsize; 10146fe57b42Smillert 10156fe57b42Smillert if (p == NULL) { 10166fe57b42Smillert p = getstring(lp, "partition to change size", 10176fe57b42Smillert "The letter of the partition to change size, a - p.", NULL); 10186fe57b42Smillert } 101996a888c6Smillert if (p == NULL) { 102096a888c6Smillert fputs("Command aborted\n", stderr); 102196a888c6Smillert return; 102296a888c6Smillert } 10236fe57b42Smillert partno = p[0] - 'a'; 10246fe57b42Smillert if (partno < 0 || partno >= lp->d_npartitions) { 10256fe57b42Smillert fprintf(stderr, "Partition must be between 'a' and '%c'.\n", 10266fe57b42Smillert 'a' + lp->d_npartitions - 1); 10276fe57b42Smillert return; 10286fe57b42Smillert } else if (partno >= lp->d_npartitions || 1029229f463eSmillert lp->d_partitions[partno].p_size == 0) { 10306fe57b42Smillert fprintf(stderr, "Partition '%c' is not in use.\n", 'a' + partno); 10316fe57b42Smillert return; 10326fe57b42Smillert } 10336fe57b42Smillert 10346fe57b42Smillert printf("Partition %c is currently %u sectors in size (%u free).\n", 10356fe57b42Smillert partno + 'a', lp->d_partitions[partno].p_size, *freep); 1036229f463eSmillert /* XXX - make maxsize lp->d_secperunit if FS_UNUSED/FS_BOOT? */ 10376fe57b42Smillert newsize = getuint(lp, partno, "new size", "Size of the partition. " 10386fe57b42Smillert "You may also say +/- amount for a relative change.", 10396fe57b42Smillert lp->d_partitions[partno].p_size, 10406fe57b42Smillert lp->d_partitions[partno].p_size + *freep, DO_CONVERSIONS | 10416fe57b42Smillert (lp->d_partitions[partno].p_fstype == FS_BSDFFS ? DO_ROUNDING : 0)); 104296a888c6Smillert if (newsize == UINT_MAX - 1) { 104396a888c6Smillert fputs("Command aborted\n", stderr); 104496a888c6Smillert return; 104596a888c6Smillert } else if (newsize == UINT_MAX) { 10466fe57b42Smillert fputs("Invalid entry\n", stderr); 10476fe57b42Smillert return; 10486fe57b42Smillert } else if (newsize == lp->d_partitions[partno].p_size) 10496fe57b42Smillert return; 10506fe57b42Smillert 1051229f463eSmillert if (lp->d_partitions[partno].p_fstype != FS_UNUSED && 1052229f463eSmillert lp->d_partitions[partno].p_fstype != FS_BOOT) { 10536fe57b42Smillert if (newsize > lp->d_partitions[partno].p_size) { 10546fe57b42Smillert if (newsize - lp->d_partitions[partno].p_size > *freep) { 10556fe57b42Smillert fprintf(stderr, 10566fe57b42Smillert "Only %u sectors free, you asked for %u\n", 10576fe57b42Smillert *freep, 10586fe57b42Smillert newsize - lp->d_partitions[partno].p_size); 10596fe57b42Smillert return; 10606fe57b42Smillert } 10616fe57b42Smillert *freep -= newsize - lp->d_partitions[partno].p_size; 10626fe57b42Smillert } else if (newsize < lp->d_partitions[partno].p_size) { 10636fe57b42Smillert *freep += lp->d_partitions[partno].p_size - newsize; 10646fe57b42Smillert } 10656fe57b42Smillert } else { 106696a888c6Smillert if (partno == 2 && newsize + 10676fe57b42Smillert lp->d_partitions[partno].p_offset > lp->d_secperunit) { 10686fe57b42Smillert fputs("'c' partition may not be larger than the disk\n", 10696fe57b42Smillert stderr); 10706fe57b42Smillert return; 10716fe57b42Smillert } 10726fe57b42Smillert } 10736fe57b42Smillert lp->d_partitions[partno].p_size = newsize; 107496a888c6Smillert if (newsize + lp->d_partitions[partno].p_offset > ending_sector || 107596a888c6Smillert has_overlap(lp, freep, -1)) 10766fe57b42Smillert make_contiguous(lp); 10776fe57b42Smillert } 10786fe57b42Smillert 10796fe57b42Smillert void 10806fe57b42Smillert make_contiguous(lp) 10816fe57b42Smillert struct disklabel *lp; 10826fe57b42Smillert { 10836fe57b42Smillert struct partition **spp; 10846fe57b42Smillert u_int16_t npartitions; 10856fe57b42Smillert int i; 10866fe57b42Smillert 1087a7e61405Smillert /* Get a sorted list of the partitions */ 108896a888c6Smillert if ((spp = sort_partitions(lp, &npartitions)) == NULL) 108996a888c6Smillert return; 10906fe57b42Smillert 10916fe57b42Smillert /* 1092a7e61405Smillert * Make everything contiguous but don't muck with start of the first one 109396a888c6Smillert * or partitions not in the BSD part of the label. 10946fe57b42Smillert */ 109596a888c6Smillert for (i = 1; i < npartitions; i++) { 109696a888c6Smillert if (spp[i]->p_offset >= starting_sector || 109796a888c6Smillert spp[i]->p_offset < ending_sector) 109896a888c6Smillert spp[i]->p_offset = 109996a888c6Smillert spp[i - 1]->p_offset + spp[i - 1]->p_size; 110096a888c6Smillert } 1101f0b4d0a9Smillert 1102f0b4d0a9Smillert (void)free(spp); 11036fe57b42Smillert } 11046fe57b42Smillert 11056fe57b42Smillert /* 11066fe57b42Smillert * Sort the partitions based on starting offset. 11076fe57b42Smillert * This assumes there can be no overlap. 11086fe57b42Smillert */ 11096fe57b42Smillert int 11106fe57b42Smillert partition_cmp(e1, e2) 11116fe57b42Smillert const void *e1, *e2; 11126fe57b42Smillert { 11136fe57b42Smillert struct partition *p1 = *(struct partition **)e1; 11146fe57b42Smillert struct partition *p2 = *(struct partition **)e2; 11156fe57b42Smillert 11166fe57b42Smillert return((int)(p1->p_offset - p2->p_offset)); 11176fe57b42Smillert } 11186fe57b42Smillert 11196fe57b42Smillert char * 11206fe57b42Smillert getstring(lp, prompt, helpstring, oval) 11216fe57b42Smillert struct disklabel *lp; 11226fe57b42Smillert char *prompt; 11236fe57b42Smillert char *helpstring; 11246fe57b42Smillert char *oval; 11256fe57b42Smillert { 11266fe57b42Smillert static char buf[BUFSIZ]; 11276fe57b42Smillert int n; 11286fe57b42Smillert 11296fe57b42Smillert buf[0] = '\0'; 11306fe57b42Smillert do { 11316fe57b42Smillert printf("%s: [%s] ", prompt, oval ? oval : ""); 11326fe57b42Smillert fflush(stdout); 11336fe57b42Smillert rewind(stdin); 11346e0becc5Smillert if (fgets(buf, sizeof(buf), stdin) == NULL) { 1135260513deSmillert buf[0] = '\0'; 113696a888c6Smillert if (feof(stdin)) { 113796a888c6Smillert putchar('\n'); 113896a888c6Smillert return(NULL); 113996a888c6Smillert } 11406e0becc5Smillert } 11416fe57b42Smillert n = strlen(buf); 11426fe57b42Smillert if (n > 0 && buf[n-1] == '\n') 11436fe57b42Smillert buf[--n] = '\0'; 11446fe57b42Smillert if (buf[0] == '?') 11456fe57b42Smillert puts(helpstring); 11466fe57b42Smillert else if (oval != NULL && buf[0] == '\0') { 11476fe57b42Smillert (void)strncpy(buf, oval, sizeof(buf) - 1); 11486fe57b42Smillert buf[sizeof(buf) - 1] = '\0'; 11496fe57b42Smillert } 11506fe57b42Smillert } while (buf[0] == '?'); 11516fe57b42Smillert 11526fe57b42Smillert return(&buf[0]); 11536fe57b42Smillert } 11546fe57b42Smillert 11556fe57b42Smillert /* 11566fe57b42Smillert * Returns UINT_MAX on error 11576fe57b42Smillert * XXX - there are way too many parameters here. Use inline helper functions 11586fe57b42Smillert */ 11596fe57b42Smillert u_int32_t 11606fe57b42Smillert getuint(lp, partno, prompt, helpstring, oval, maxval, flags) 11616fe57b42Smillert struct disklabel *lp; 11626fe57b42Smillert int partno; 11636fe57b42Smillert char *prompt; 11646fe57b42Smillert char *helpstring; 11656fe57b42Smillert u_int32_t oval; 11666fe57b42Smillert u_int32_t maxval; /* XXX - used inconsistently */ 11676fe57b42Smillert int flags; 11686fe57b42Smillert { 11696fe57b42Smillert char buf[BUFSIZ], *endptr, *p, operator = '\0'; 11706fe57b42Smillert u_int32_t rval = oval; 11716fe57b42Smillert size_t n; 11726fe57b42Smillert int mult = 1; 117396a888c6Smillert double d; 11746fe57b42Smillert 11756fe57b42Smillert buf[0] = '\0'; 11766fe57b42Smillert do { 11776fe57b42Smillert printf("%s: [%u] ", prompt, oval); 11786fe57b42Smillert fflush(stdout); 11796fe57b42Smillert rewind(stdin); 11806e0becc5Smillert if (fgets(buf, sizeof(buf), stdin) == NULL) { 11816e0becc5Smillert buf[0] = '\0'; 118296a888c6Smillert if (feof(stdin)) { 118396a888c6Smillert putchar('\n'); 118496a888c6Smillert return(UINT_MAX - 1); 118596a888c6Smillert } 11866e0becc5Smillert } 11876fe57b42Smillert n = strlen(buf); 11886fe57b42Smillert if (n > 0 && buf[n-1] == '\n') 11896fe57b42Smillert buf[--n] = '\0'; 11906fe57b42Smillert if (buf[0] == '?') 11916fe57b42Smillert puts(helpstring); 11926fe57b42Smillert } while (buf[0] == '?'); 11936fe57b42Smillert 11946fe57b42Smillert if (buf[0] == '*' && buf[1] == '\0') { 11956fe57b42Smillert rval = maxval; 11966fe57b42Smillert } else { 11976fe57b42Smillert /* deal with units */ 11986fe57b42Smillert if (buf[0] != '\0' && n > 0) { 11996fe57b42Smillert if ((flags & DO_CONVERSIONS)) { 120096a888c6Smillert switch (tolower(buf[n-1])) { 12016fe57b42Smillert 12026fe57b42Smillert case 'c': 12036fe57b42Smillert mult = lp->d_secpercyl; 12046fe57b42Smillert buf[--n] = '\0'; 12056fe57b42Smillert break; 12066fe57b42Smillert case 'b': 12076fe57b42Smillert mult = -lp->d_secsize; 12086fe57b42Smillert buf[--n] = '\0'; 12096fe57b42Smillert break; 12106fe57b42Smillert case 'k': 12116fe57b42Smillert mult = 1024 / lp->d_secsize; 12126fe57b42Smillert buf[--n] = '\0'; 12136fe57b42Smillert break; 12146fe57b42Smillert case 'm': 12156fe57b42Smillert mult = 1048576 / lp->d_secsize; 12166fe57b42Smillert buf[--n] = '\0'; 12176fe57b42Smillert break; 12181a51a1eeSmillert case 'g': 12191a51a1eeSmillert mult = 1073741824 / lp->d_secsize; 12201a51a1eeSmillert buf[--n] = '\0'; 12211a51a1eeSmillert break; 12226fe57b42Smillert } 122396a888c6Smillert } 12246fe57b42Smillert 12256fe57b42Smillert /* Did they give us an operator? */ 12266fe57b42Smillert p = &buf[0]; 12276fe57b42Smillert if (*p == '+' || *p == '-') 12286fe57b42Smillert operator = *p++; 12296fe57b42Smillert 12306fe57b42Smillert endptr = p; 123196a888c6Smillert errno = 0; 123296a888c6Smillert d = strtod(p, &endptr); 123396a888c6Smillert if (errno == ERANGE) 123496a888c6Smillert rval = UINT_MAX; /* too big/small */ 123596a888c6Smillert else if (*endptr != '\0') { 12366fe57b42Smillert errno = EINVAL; /* non-numbers in str */ 12376fe57b42Smillert rval = UINT_MAX; 12386fe57b42Smillert } else { 123996a888c6Smillert /* XXX - should check for overflow */ 124096a888c6Smillert if (mult > 0) 124196a888c6Smillert rval = d * mult; 124296a888c6Smillert else 124396a888c6Smillert /* Negative mult means divide (fancy) */ 124496a888c6Smillert rval = d / (-mult); 12456fe57b42Smillert 124696a888c6Smillert /* Apply the operator */ 12476fe57b42Smillert if (operator == '+') 12486fe57b42Smillert rval += oval; 12496fe57b42Smillert else if (operator == '-') 12506fe57b42Smillert rval = oval - rval; 12516fe57b42Smillert } 12526fe57b42Smillert } 12536fe57b42Smillert } 12546fe57b42Smillert if ((flags & DO_ROUNDING) && rval < UINT_MAX) { 12556fe57b42Smillert u_int32_t cyls; 1256260513deSmillert /* XXX - should use maxsize and round down if too big */ 12576fe57b42Smillert #ifdef CYLCHECK 12586fe57b42Smillert /* Always round to nearest cylinder, regardless of units */ 12596fe57b42Smillert cyls = (u_int32_t)((rval / (double)lp->d_secpercyl) + 0.5); 12606fe57b42Smillert if (rval != cyls * lp->d_secpercyl) { 12616fe57b42Smillert rval = cyls * lp->d_secpercyl; 12626fe57b42Smillert printf("Rounding to nearest cylinder: %u\n", rval); 12636fe57b42Smillert } 12646fe57b42Smillert #else 126596a888c6Smillert /* Round to nearest cylinder unless given in sectors */ 126696a888c6Smillert if (mult != 1) { 12676fe57b42Smillert cyls = (u_int32_t)((rval / (double)lp->d_secpercyl) 12686fe57b42Smillert + 0.5); 12696fe57b42Smillert if (rval != cyls * lp->d_secpercyl) { 12706fe57b42Smillert rval = cyls * lp->d_secpercyl; 12716fe57b42Smillert printf("Rounding to nearest cylinder: %u\n", 12726fe57b42Smillert rval); 12736fe57b42Smillert } 12746fe57b42Smillert } 12756fe57b42Smillert #endif 12766fe57b42Smillert } 12776fe57b42Smillert 12786fe57b42Smillert return(rval); 12796fe57b42Smillert } 12806fe57b42Smillert 12816fe57b42Smillert /* 12826fe57b42Smillert * Check for partition overlap in lp and prompt the user 12836fe57b42Smillert * to resolve the overlap if any is found. Returns 1 12846fe57b42Smillert * if unable to resolve, else 0. 12856fe57b42Smillert */ 12866fe57b42Smillert int 12876fe57b42Smillert has_overlap(lp, freep, resolve) 12886fe57b42Smillert struct disklabel *lp; 12896fe57b42Smillert u_int32_t *freep; 12906fe57b42Smillert int resolve; 12916fe57b42Smillert { 12926fe57b42Smillert struct partition **spp; 12936fe57b42Smillert u_int16_t npartitions; 1294e6aa8bafSmillert int c, i, j; 1295e6aa8bafSmillert char buf[BUFSIZ]; 12966fe57b42Smillert 1297a7e61405Smillert /* Get a sorted list of the partitions */ 1298a7e61405Smillert spp = sort_partitions(lp, &npartitions); 12996fe57b42Smillert 1300a7e61405Smillert if (npartitions < 2) { 1301a7e61405Smillert (void)free(spp); 13026fe57b42Smillert return(0); /* nothing to do */ 13036fe57b42Smillert } 13046fe57b42Smillert 13056fe57b42Smillert /* Now that we have things sorted by starting sector check overlap */ 13066fe57b42Smillert for (i = 0; i < npartitions; i++) { 13076fe57b42Smillert for (j = i + 1; j < npartitions; j++) { 13086fe57b42Smillert /* `if last_sec_in_part + 1 > first_sec_in_next_part' */ 13096fe57b42Smillert if (spp[i]->p_offset + spp[i]->p_size > spp[j]->p_offset) { 131096a888c6Smillert /* Don't print, just return */ 131196a888c6Smillert if (resolve == -1) { 131296a888c6Smillert (void)free(spp); 131396a888c6Smillert return(1); 131496a888c6Smillert } 131596a888c6Smillert 13166fe57b42Smillert /* Overlap! Convert to real part numbers. */ 13176fe57b42Smillert i = ((char *)spp[i] - (char *)lp->d_partitions) 13186fe57b42Smillert / sizeof(**spp); 13196fe57b42Smillert j = ((char *)spp[j] - (char *)lp->d_partitions) 13206fe57b42Smillert / sizeof(**spp); 13216fe57b42Smillert printf("\nError, partitions %c and %c overlap:\n", 13226fe57b42Smillert 'a' + i, 'a' + j); 13236fe57b42Smillert puts(" size offset fstype [fsize bsize cpg]"); 1324af98caf3Sderaadt display_partition(stdout, lp, i, 0, 0); 1325af98caf3Sderaadt display_partition(stdout, lp, j, 0, 0); 13266fe57b42Smillert 13276fe57b42Smillert /* Did they ask us to resolve it ourselves? */ 132896a888c6Smillert if (resolve != 1) { 1329f0b4d0a9Smillert (void)free(spp); 13306fe57b42Smillert return(1); 1331f0b4d0a9Smillert } 13326fe57b42Smillert 1333e6aa8bafSmillert /* Get partition to disable or ^D */ 1334e6aa8bafSmillert do { 1335616cd1c4Smillert printf("Disable which one? (^D to abort) [%c %c] ", 13366fe57b42Smillert 'a' + i, 'a' + j); 1337e6aa8bafSmillert buf[0] = '\0'; 1338616cd1c4Smillert if (!fgets(buf, sizeof(buf), stdin)) { 1339616cd1c4Smillert putchar('\n'); 1340e6aa8bafSmillert return(1); /* ^D */ 1341616cd1c4Smillert } 1342e6aa8bafSmillert c = buf[0] - 'a'; 1343e6aa8bafSmillert } while (buf[1] != '\n' && buf[1] != '\0' && 1344e6aa8bafSmillert c != i && c != j); 1345e6aa8bafSmillert 1346e6aa8bafSmillert /* Mark the selected one as unused */ 13476fe57b42Smillert lp->d_partitions[c].p_fstype = FS_UNUSED; 13486fe57b42Smillert *freep += lp->d_partitions[c].p_size; 1349e6aa8bafSmillert (void)free(spp); 1350e6aa8bafSmillert return(has_overlap(lp, freep, resolve)); 13516fe57b42Smillert } 13526fe57b42Smillert } 13536fe57b42Smillert } 1354f0b4d0a9Smillert 1355f0b4d0a9Smillert (void)free(spp); 1356e6aa8bafSmillert return(0); 13576fe57b42Smillert } 13586fe57b42Smillert 13596fe57b42Smillert void 13606fe57b42Smillert edit_parms(lp, freep) 13616fe57b42Smillert struct disklabel *lp; 13626fe57b42Smillert u_int32_t *freep; 13636fe57b42Smillert { 13646fe57b42Smillert char *p; 13656fe57b42Smillert u_int32_t ui; 136696a888c6Smillert struct disklabel oldlabel = *lp; 13676fe57b42Smillert 1368ea37abd3Sderaadt printf("Changing device parameters for %s:\n", specname); 13696fe57b42Smillert 13700f820bbbSmillert /* disk type */ 13710f820bbbSmillert for (;;) { 13720f820bbbSmillert p = getstring(lp, "disk type", 137341282a2aSmillert "What kind of disk is this? Usually SCSI, ESDI, ST506, or " 137441282a2aSmillert "floppy (use ESDI for IDE).", dktypenames[lp->d_type]); 137596a888c6Smillert if (p == NULL) { 137696a888c6Smillert fputs("Command aborted\n", stderr); 137796a888c6Smillert return; 137896a888c6Smillert } 137941282a2aSmillert if (strcasecmp(p, "IDE") == 0) 138041282a2aSmillert ui = DTYPE_ESDI; 138141282a2aSmillert else 138241282a2aSmillert for (ui = 1; ui < DKMAXTYPES && 138341282a2aSmillert strcasecmp(p, dktypenames[ui]); ui++) 13840f820bbbSmillert ; 13850f820bbbSmillert if (ui < DKMAXTYPES) { 13860f820bbbSmillert break; 13870f820bbbSmillert } else { 13880f820bbbSmillert printf("\"%s\" is not a valid disk type.\n", p); 13890f820bbbSmillert fputs("Valid types are: ", stdout); 13900f820bbbSmillert for (ui = 1; ui < DKMAXTYPES; ui++) { 13910f820bbbSmillert printf("\"%s\"", dktypenames[ui]); 13920f820bbbSmillert if (ui < DKMAXTYPES - 1) 13930f820bbbSmillert fputs(", ", stdout); 13940f820bbbSmillert } 13950f820bbbSmillert putchar('\n'); 13960f820bbbSmillert } 13970f820bbbSmillert } 13980f820bbbSmillert lp->d_type = ui; 13990f820bbbSmillert 14006fe57b42Smillert /* pack/label id */ 14016fe57b42Smillert p = getstring(lp, "label name", 14026fe57b42Smillert "15 char string that describes this label, usually the disk name.", 14036fe57b42Smillert lp->d_packname); 140496a888c6Smillert if (p == NULL) { 140596a888c6Smillert fputs("Command aborted\n", stderr); 140696a888c6Smillert *lp = oldlabel; /* undo damage */ 140796a888c6Smillert return; 140896a888c6Smillert } 14096fe57b42Smillert strncpy(lp->d_packname, p, sizeof(lp->d_packname) - 1); 14106fe57b42Smillert lp->d_packname[sizeof(lp->d_packname) - 1] = '\0'; 14116fe57b42Smillert 14126fe57b42Smillert /* sectors/track */ 14136fe57b42Smillert for (;;) { 14146fe57b42Smillert ui = getuint(lp, 0, "sectors/track", 14156fe57b42Smillert "The Numer of sectors per track.", lp->d_nsectors, 14166fe57b42Smillert lp->d_nsectors, 0); 141796a888c6Smillert if (ui == UINT_MAX - 1) { 141896a888c6Smillert fputs("Command aborted\n", stderr); 141996a888c6Smillert *lp = oldlabel; /* undo damage */ 142096a888c6Smillert return; 142196a888c6Smillert } if (ui == UINT_MAX) 14226fe57b42Smillert fputs("Invalid entry\n", stderr); 14236fe57b42Smillert else 14246fe57b42Smillert break; 14256fe57b42Smillert } 14266fe57b42Smillert lp->d_nsectors = ui; 14276fe57b42Smillert 14286fe57b42Smillert /* tracks/cylinder */ 14296fe57b42Smillert for (;;) { 14306fe57b42Smillert ui = getuint(lp, 0, "tracks/cylinder", 14316fe57b42Smillert "The number of tracks per cylinder.", lp->d_ntracks, 14326fe57b42Smillert lp->d_ntracks, 0); 143396a888c6Smillert if (ui == UINT_MAX - 1) { 143496a888c6Smillert fputs("Command aborted\n", stderr); 143596a888c6Smillert *lp = oldlabel; /* undo damage */ 143696a888c6Smillert return; 143796a888c6Smillert } else if (ui == UINT_MAX) 14386fe57b42Smillert fputs("Invalid entry\n", stderr); 14396fe57b42Smillert else 14406fe57b42Smillert break; 14416fe57b42Smillert } 14426fe57b42Smillert lp->d_ntracks = ui; 14436fe57b42Smillert 14446fe57b42Smillert /* sectors/cylinder */ 1445148b6188Smillert for (;;) { 1446148b6188Smillert ui = getuint(lp, 0, "sectors/cylinder", 1447148b6188Smillert "The number of sectors per cylinder (Usually sectors/track " 1448148b6188Smillert "* tracks/cylinder).", lp->d_secpercyl, lp->d_secpercyl, 0); 144996a888c6Smillert if (ui == UINT_MAX - 1) { 145096a888c6Smillert fputs("Command aborted\n", stderr); 145196a888c6Smillert *lp = oldlabel; /* undo damage */ 145296a888c6Smillert return; 145396a888c6Smillert } else if (ui == UINT_MAX) 1454148b6188Smillert fputs("Invalid entry\n", stderr); 1455148b6188Smillert else 1456148b6188Smillert break; 1457148b6188Smillert } 1458148b6188Smillert lp->d_secpercyl = ui; 14596fe57b42Smillert 14606fe57b42Smillert /* number of cylinders */ 14616fe57b42Smillert for (;;) { 14626fe57b42Smillert ui = getuint(lp, 0, "number of cylinders", 14636fe57b42Smillert "The total number of cylinders on the disk.", 14646fe57b42Smillert lp->d_ncylinders, lp->d_ncylinders, 0); 146596a888c6Smillert if (ui == UINT_MAX - 1) { 146696a888c6Smillert fputs("Command aborted\n", stderr); 146796a888c6Smillert *lp = oldlabel; /* undo damage */ 146896a888c6Smillert return; 146996a888c6Smillert } else if (ui == UINT_MAX) 14706fe57b42Smillert fputs("Invalid entry\n", stderr); 14716fe57b42Smillert else 14726fe57b42Smillert break; 14736fe57b42Smillert } 14746fe57b42Smillert lp->d_ncylinders = ui; 14756fe57b42Smillert 14766fe57b42Smillert /* total sectors */ 14776fe57b42Smillert for (;;) { 14786fe57b42Smillert ui = getuint(lp, 0, "total sectors", 14796fe57b42Smillert "The total number of sectors on the disk.", 14806fe57b42Smillert lp->d_secperunit ? lp->d_secperunit : 14816fe57b42Smillert lp->d_ncylinders * lp->d_ncylinders, 14826fe57b42Smillert lp->d_ncylinders * lp->d_ncylinders, 0); 148396a888c6Smillert if (ui == UINT_MAX - 1) { 148496a888c6Smillert fputs("Command aborted\n", stderr); 148596a888c6Smillert *lp = oldlabel; /* undo damage */ 148696a888c6Smillert return; 148796a888c6Smillert } else if (ui == UINT_MAX) 14886fe57b42Smillert fputs("Invalid entry\n", stderr); 148996a888c6Smillert else if (ui > lp->d_secperunit && 149096a888c6Smillert ending_sector == lp->d_secperunit) { 14916fe57b42Smillert /* grow free count */ 14926fe57b42Smillert *freep += ui - lp->d_secperunit; 1493f98aebd4Smillert puts("You may want to increase the size of the 'c' " 1494f98aebd4Smillert "partition."); 14956fe57b42Smillert break; 149696a888c6Smillert } else if (ui < lp->d_secperunit && 149796a888c6Smillert ending_sector == lp->d_secperunit) { 14986fe57b42Smillert /* shrink free count */ 14996fe57b42Smillert if (lp->d_secperunit - ui > *freep) 15006fe57b42Smillert fprintf(stderr, 15016fe57b42Smillert "Not enough free space to shrink by %u " 15026fe57b42Smillert "sectors (only %u sectors left)\n", 15036fe57b42Smillert lp->d_secperunit - ui, *freep); 15046fe57b42Smillert else { 15056fe57b42Smillert *freep -= lp->d_secperunit - ui; 15066fe57b42Smillert break; 15076fe57b42Smillert } 15086fe57b42Smillert } else 15096fe57b42Smillert break; 15106fe57b42Smillert } 151196a888c6Smillert /* Adjust ending_sector if necesary. */ 151296a888c6Smillert if (ending_sector > ui) 151396a888c6Smillert ending_sector = ui; 15146fe57b42Smillert lp->d_secperunit = ui; 15156fe57b42Smillert 15166fe57b42Smillert /* rpm */ 15176fe57b42Smillert for (;;) { 15186fe57b42Smillert ui = getuint(lp, 0, "rpm", 1519a7e61405Smillert "The rotational speed of the disk in revolutions per minute.", 15206fe57b42Smillert lp->d_rpm, lp->d_rpm, 0); 152196a888c6Smillert if (ui == UINT_MAX - 1) { 152296a888c6Smillert fputs("Command aborted\n", stderr); 152396a888c6Smillert *lp = oldlabel; /* undo damage */ 152496a888c6Smillert return; 152596a888c6Smillert } else if (ui == UINT_MAX) 15266fe57b42Smillert fputs("Invalid entry\n", stderr); 15276fe57b42Smillert else 15286fe57b42Smillert break; 15296fe57b42Smillert } 15306fe57b42Smillert lp->d_rpm = ui; 15316fe57b42Smillert } 1532a7e61405Smillert 1533a7e61405Smillert struct partition ** 1534a7e61405Smillert sort_partitions(lp, npart) 1535a7e61405Smillert struct disklabel *lp; 1536a7e61405Smillert u_int16_t *npart; 1537a7e61405Smillert { 1538a7e61405Smillert u_int16_t npartitions; 1539a7e61405Smillert struct partition **spp; 1540a7e61405Smillert int i; 1541a7e61405Smillert 1542a7e61405Smillert /* How many "real" partitions do we have? */ 1543a7e61405Smillert for (npartitions = 0, i = 0; i < lp->d_npartitions; i++) { 1544a7e61405Smillert if (lp->d_partitions[i].p_fstype != FS_UNUSED && 1545a7e61405Smillert lp->d_partitions[i].p_fstype != FS_BOOT && 1546a7e61405Smillert lp->d_partitions[i].p_size != 0) 1547a7e61405Smillert npartitions++; 1548a7e61405Smillert } 154996a888c6Smillert if (npartitions == 0) { 155096a888c6Smillert *npart = 0; 155196a888c6Smillert return(NULL); 155296a888c6Smillert } 1553a7e61405Smillert 1554a7e61405Smillert /* Create an array of pointers to the partition data */ 1555a7e61405Smillert if ((spp = malloc(sizeof(struct partition *) * npartitions)) == NULL) 1556a7e61405Smillert errx(4, "out of memory"); 1557a7e61405Smillert for (npartitions = 0, i = 0; i < lp->d_npartitions; i++) { 1558a7e61405Smillert if (lp->d_partitions[i].p_fstype != FS_UNUSED && 1559a7e61405Smillert lp->d_partitions[i].p_fstype != FS_BOOT && 1560a7e61405Smillert lp->d_partitions[i].p_size != 0) 1561a7e61405Smillert spp[npartitions++] = &lp->d_partitions[i]; 1562a7e61405Smillert } 1563a7e61405Smillert 1564a7e61405Smillert /* 1565a7e61405Smillert * Sort the partitions based on starting offset. 1566a7e61405Smillert * This is safe because we guarantee no overlap. 1567a7e61405Smillert */ 1568a7e61405Smillert if (npartitions > 1) 1569a7e61405Smillert if (heapsort((void *)spp, npartitions, sizeof(spp[0]), 1570a7e61405Smillert partition_cmp)) 1571a7e61405Smillert err(4, "failed to sort partition table"); 1572a7e61405Smillert 1573a7e61405Smillert *npart = npartitions; 1574a7e61405Smillert return(spp); 1575a7e61405Smillert } 15760f820bbbSmillert 15770f820bbbSmillert /* 15780f820bbbSmillert * Get a valid disk type if necessary. 15790f820bbbSmillert */ 15800f820bbbSmillert void 15810f820bbbSmillert getdisktype(lp, banner) 15820f820bbbSmillert struct disklabel *lp; 15830f820bbbSmillert char *banner; 15840f820bbbSmillert { 15850f820bbbSmillert int i; 15860f820bbbSmillert char *s; 15870f820bbbSmillert 15880f820bbbSmillert if (lp->d_type > DKMAXTYPES || lp->d_type == 0) { 15890f820bbbSmillert puts(banner); 15900f820bbbSmillert puts("Possible values are:"); 1591eb5dd924Sderaadt printf("\"IDE\", "); 15920f820bbbSmillert for (i = 1; i < DKMAXTYPES; i++) { 15930f820bbbSmillert printf("\"%s\"", dktypenames[i]); 15940f820bbbSmillert if (i < DKMAXTYPES - 1) 15950f820bbbSmillert fputs(", ", stdout); 15960f820bbbSmillert } 15970f820bbbSmillert putchar('\n'); 15980f820bbbSmillert 15990f820bbbSmillert for (;;) { 16000f820bbbSmillert s = getstring(lp, "Disk type", 16015b412421Smillert "What kind of disk is this? Usually SCSI, ESDI, " 16025b412421Smillert "ST506, or floppy (use ESDI for IDE).", 16030f820bbbSmillert "SCSI"); 160496a888c6Smillert if (s == NULL) 160596a888c6Smillert continue; 16065b412421Smillert if (strcasecmp(s, "IDE") == 0) { 16075b412421Smillert lp->d_type = DTYPE_ESDI; 16085b412421Smillert putchar('\n'); 16095b412421Smillert return; 16105b412421Smillert } 16110f820bbbSmillert for (i = 1; i < DKMAXTYPES; i++) 16120f820bbbSmillert if (strcasecmp(s, dktypenames[i]) == 0) { 16130f820bbbSmillert lp->d_type = i; 16140f820bbbSmillert putchar('\n'); 16150f820bbbSmillert return; 16160f820bbbSmillert } 16170f820bbbSmillert printf("\"%s\" is not a valid disk type.\n", s); 16180f820bbbSmillert fputs("Valid types are: ", stdout); 16190f820bbbSmillert for (i = 1; i < DKMAXTYPES; i++) { 16200f820bbbSmillert printf("\"%s\"", dktypenames[i]); 16210f820bbbSmillert if (i < DKMAXTYPES - 1) 16220f820bbbSmillert fputs(", ", stdout); 16230f820bbbSmillert } 16240f820bbbSmillert putchar('\n'); 16250f820bbbSmillert } 16260f820bbbSmillert } 16270f820bbbSmillert } 162896a888c6Smillert 162996a888c6Smillert /* 163096a888c6Smillert * Get beginning and ending sectors of the OpenBSD portion of the disk 163196a888c6Smillert * from the user. 16324793b14cSmillert * XXX - should mention MBR values if DOSLABEL 163396a888c6Smillert */ 163496a888c6Smillert void 1635e8e8bdb7Sart set_bounds(lp, freep) 163696a888c6Smillert struct disklabel *lp; 1637e8e8bdb7Sart u_int32_t *freep; 163896a888c6Smillert { 163996a888c6Smillert u_int32_t ui, start_temp; 164096a888c6Smillert 164196a888c6Smillert /* Starting sector */ 164296a888c6Smillert do { 164396a888c6Smillert ui = getuint(lp, 0, "Starting sector", 164496a888c6Smillert "The start of the OpenBSD portion of the disk.", 164596a888c6Smillert starting_sector, lp->d_secperunit, 0); 164696a888c6Smillert if (ui == UINT_MAX - 1) { 164796a888c6Smillert fputs("Command aborted\n", stderr); 164896a888c6Smillert return; 164996a888c6Smillert } 165096a888c6Smillert } while (ui >= lp->d_secperunit); 165196a888c6Smillert start_temp = ui; 165296a888c6Smillert 16534793b14cSmillert /* Size */ 165496a888c6Smillert do { 1655f98aebd4Smillert ui = getuint(lp, 0, "Size ('*' for entire disk)", 1656f98aebd4Smillert "The size of the OpenBSD portion of the disk ('*' for the " 1657f98aebd4Smillert "entire disk).", ending_sector - starting_sector, 1658f98aebd4Smillert lp->d_secperunit - start_temp, 0); 165996a888c6Smillert if (ui == UINT_MAX - 1) { 166096a888c6Smillert fputs("Command aborted\n", stderr); 166196a888c6Smillert return; 166296a888c6Smillert } 1663f98aebd4Smillert } while (ui > lp->d_secperunit - start_temp); 16644793b14cSmillert ending_sector = start_temp + ui; 166596a888c6Smillert starting_sector = start_temp; 1666e8e8bdb7Sart 1667e8e8bdb7Sart /* Recalculate the free sectors */ 1668c0bdc608Smillert editor_countfree(lp, freep); 166996a888c6Smillert } 167096a888c6Smillert 167196a888c6Smillert /* 167296a888c6Smillert * Return a list of the "chunks" of free space available 167396a888c6Smillert */ 167496a888c6Smillert struct diskchunk * 167596a888c6Smillert free_chunks(lp) 167696a888c6Smillert struct disklabel *lp; 167796a888c6Smillert { 167896a888c6Smillert u_int16_t npartitions; 167996a888c6Smillert struct partition **spp; 168096a888c6Smillert static struct diskchunk chunks[MAXPARTITIONS + 2]; 168196a888c6Smillert int i, numchunks; 168296a888c6Smillert 168396a888c6Smillert /* Sort the partitions based on offset */ 168496a888c6Smillert spp = sort_partitions(lp, &npartitions); 168596a888c6Smillert 168696a888c6Smillert /* If there are no partitions, it's all free. */ 168796a888c6Smillert if (spp == NULL) { 168896a888c6Smillert chunks[0].start = 0; 168996a888c6Smillert chunks[0].stop = ending_sector; 169096a888c6Smillert chunks[1].start = chunks[1].stop = 0; 169196a888c6Smillert return(chunks); 169296a888c6Smillert } 169396a888c6Smillert 169496a888c6Smillert /* Find chunks of free space */ 169596a888c6Smillert numchunks = 0; 169696a888c6Smillert if (spp && spp[0]->p_offset > 0) { 169796a888c6Smillert chunks[0].start = 0; 169896a888c6Smillert chunks[0].stop = spp[0]->p_offset; 169996a888c6Smillert numchunks++; 170096a888c6Smillert } 170196a888c6Smillert for (i = 0; i < npartitions; i++) { 170296a888c6Smillert if (i + 1 < npartitions) { 170396a888c6Smillert if (spp[i]->p_offset + spp[i]->p_size < spp[i+1]->p_offset) { 170496a888c6Smillert chunks[numchunks].start = 170596a888c6Smillert spp[i]->p_offset + spp[i]->p_size; 170696a888c6Smillert chunks[numchunks].stop = spp[i+1]->p_offset; 170796a888c6Smillert numchunks++; 170896a888c6Smillert } 170996a888c6Smillert } else { 171096a888c6Smillert /* Last partition */ 171196a888c6Smillert if (spp[i]->p_offset + spp[i]->p_size < lp->d_secperunit) { 171296a888c6Smillert 171396a888c6Smillert chunks[numchunks].start = 171496a888c6Smillert spp[i]->p_offset + spp[i]->p_size; 171596a888c6Smillert chunks[numchunks].stop = lp->d_secperunit; 171696a888c6Smillert numchunks++; 171796a888c6Smillert } 171896a888c6Smillert } 171996a888c6Smillert } 172096a888c6Smillert 172196a888c6Smillert /* Terminate and return */ 172296a888c6Smillert chunks[numchunks].start = chunks[numchunks].stop = 0; 172396a888c6Smillert (void)free(spp); 172496a888c6Smillert return(chunks); 172596a888c6Smillert } 17264793b14cSmillert 17274793b14cSmillert /* 17284793b14cSmillert * What is the OpenBSD portion of the disk? Uses the MBR if applicable. 17294793b14cSmillert */ 17304793b14cSmillert void 17314793b14cSmillert find_bounds(lp) 17324793b14cSmillert struct disklabel *lp; 17334793b14cSmillert { 1734f98aebd4Smillert struct partition *pp = &lp->d_partitions[2]; 17354793b14cSmillert 17364793b14cSmillert /* Defaults */ 17374793b14cSmillert /* XXX - reserve a cylinder for hp300? */ 17384793b14cSmillert starting_sector = 0; 17394793b14cSmillert ending_sector = lp->d_secperunit; 17404793b14cSmillert 17414793b14cSmillert #ifdef DOSLABEL 1742aaa7b57dSderaadt /* If we have an MBR, use values from the OpenBSD/FreeBSD parition. */ 1743aaa7b57dSderaadt if (dosdp && pp->p_size && 1744aaa7b57dSderaadt (dosdp->dp_typ == DOSPTYP_OPENBSD || 1745aaa7b57dSderaadt dosdp->dp_typ == DOSPTYP_FREEBSD || 1746aaa7b57dSderaadt dosdp->dp_typ == DOSPTYP_NETBSD)) { 17474793b14cSmillert starting_sector = get_le(&dosdp->dp_start); 17484793b14cSmillert ending_sector = starting_sector + get_le(&dosdp->dp_size); 17494793b14cSmillert printf("Treating sectors %u-%u as the OpenBSD portion of the " 17504793b14cSmillert "disk.\nYou can use the 'b' command to change this.\n", 17514793b14cSmillert starting_sector, ending_sector); 1752f98aebd4Smillert /* 1753f98aebd4Smillert * XXX - check to see if any BSD/SWAP partitions go beyond 1754f98aebd4Smillert * ending_sector and prompt to extend ending_sector if so. 1755f98aebd4Smillert */ 17564793b14cSmillert } 17574793b14cSmillert #endif 17584793b14cSmillert } 1759c0bdc608Smillert 1760c0bdc608Smillert /* 1761c0bdc608Smillert * Calculate free space. 1762c0bdc608Smillert */ 1763c0bdc608Smillert void 1764c0bdc608Smillert editor_countfree(lp, freep) 1765c0bdc608Smillert struct disklabel *lp; 1766c0bdc608Smillert u_int32_t *freep; 1767c0bdc608Smillert { 1768c0bdc608Smillert struct partition *pp; 1769c0bdc608Smillert int i; 1770c0bdc608Smillert 1771c0bdc608Smillert *freep = ending_sector - starting_sector; 1772c0bdc608Smillert for (i = 0; i < lp->d_npartitions; i++) { 1773c0bdc608Smillert pp = &lp->d_partitions[i]; 1774c0bdc608Smillert if (pp->p_fstype != FS_UNUSED && pp->p_fstype != FS_BOOT && 1775c0bdc608Smillert pp->p_size > 0 && 1776c0bdc608Smillert pp->p_offset + pp->p_size <= ending_sector && 1777c0bdc608Smillert pp->p_offset >= starting_sector) 1778c0bdc608Smillert *freep -= pp->p_size; 1779c0bdc608Smillert } 1780c0bdc608Smillert } 1781