10ffe40b3SMatthew Dillon /*
235a9ab8aSMatthew Dillon * Copyright (c) 2007,2020 The DragonFly Project. All rights reserved.
30ffe40b3SMatthew Dillon *
40ffe40b3SMatthew Dillon * This code is derived from software contributed to The DragonFly Project
50ffe40b3SMatthew Dillon * by Matthew Dillon <dillon@backplane.com>
60ffe40b3SMatthew Dillon *
70ffe40b3SMatthew Dillon * Redistribution and use in source and binary forms, with or without
80ffe40b3SMatthew Dillon * modification, are permitted provided that the following conditions
90ffe40b3SMatthew Dillon * are met:
100ffe40b3SMatthew Dillon *
110ffe40b3SMatthew Dillon * 1. Redistributions of source code must retain the above copyright
120ffe40b3SMatthew Dillon * notice, this list of conditions and the following disclaimer.
130ffe40b3SMatthew Dillon * 2. Redistributions in binary form must reproduce the above copyright
140ffe40b3SMatthew Dillon * notice, this list of conditions and the following disclaimer in
150ffe40b3SMatthew Dillon * the documentation and/or other materials provided with the
160ffe40b3SMatthew Dillon * distribution.
170ffe40b3SMatthew Dillon * 3. Neither the name of The DragonFly Project nor the names of its
180ffe40b3SMatthew Dillon * contributors may be used to endorse or promote products derived
190ffe40b3SMatthew Dillon * from this software without specific, prior written permission.
200ffe40b3SMatthew Dillon *
210ffe40b3SMatthew Dillon * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
220ffe40b3SMatthew Dillon * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
230ffe40b3SMatthew Dillon * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
240ffe40b3SMatthew Dillon * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
250ffe40b3SMatthew Dillon * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
260ffe40b3SMatthew Dillon * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
270ffe40b3SMatthew Dillon * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
280ffe40b3SMatthew Dillon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
290ffe40b3SMatthew Dillon * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
300ffe40b3SMatthew Dillon * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
310ffe40b3SMatthew Dillon * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
320ffe40b3SMatthew Dillon * SUCH DAMAGE.
330ffe40b3SMatthew Dillon */
340ffe40b3SMatthew Dillon /*
350ffe40b3SMatthew Dillon * Copyright (c) 1987, 1993
360ffe40b3SMatthew Dillon * The Regents of the University of California. All rights reserved.
370ffe40b3SMatthew Dillon *
380ffe40b3SMatthew Dillon * This code is derived from software contributed to Berkeley by
390ffe40b3SMatthew Dillon * Symmetric Computer Systems.
400ffe40b3SMatthew Dillon *
410ffe40b3SMatthew Dillon * Redistribution and use in source and binary forms, with or without
420ffe40b3SMatthew Dillon * modification, are permitted provided that the following conditions
430ffe40b3SMatthew Dillon * are met:
440ffe40b3SMatthew Dillon * 1. Redistributions of source code must retain the above copyright
450ffe40b3SMatthew Dillon * notice, this list of conditions and the following disclaimer.
460ffe40b3SMatthew Dillon * 2. Redistributions in binary form must reproduce the above copyright
470ffe40b3SMatthew Dillon * notice, this list of conditions and the following disclaimer in the
480ffe40b3SMatthew Dillon * documentation and/or other materials provided with the distribution.
49dc71b7abSJustin C. Sherrill * 3. Neither the name of the University nor the names of its contributors
500ffe40b3SMatthew Dillon * may be used to endorse or promote products derived from this software
510ffe40b3SMatthew Dillon * without specific prior written permission.
520ffe40b3SMatthew Dillon *
530ffe40b3SMatthew Dillon * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
540ffe40b3SMatthew Dillon * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
550ffe40b3SMatthew Dillon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
560ffe40b3SMatthew Dillon * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
570ffe40b3SMatthew Dillon * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
580ffe40b3SMatthew Dillon * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
590ffe40b3SMatthew Dillon * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
600ffe40b3SMatthew Dillon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
610ffe40b3SMatthew Dillon * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
620ffe40b3SMatthew Dillon * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
630ffe40b3SMatthew Dillon * SUCH DAMAGE.
640ffe40b3SMatthew Dillon *
650ffe40b3SMatthew Dillon * @(#)disklabel.c 1.2 (Symmetric) 11/28/85
660ffe40b3SMatthew Dillon * @(#)disklabel.c 8.2 (Berkeley) 1/7/94
670ffe40b3SMatthew Dillon * $FreeBSD: src/sbin/disklabel/disklabel.c,v 1.28.2.15 2003/01/24 16:18:16 des Exp $
680ffe40b3SMatthew Dillon */
690ffe40b3SMatthew Dillon
700ffe40b3SMatthew Dillon #include <sys/param.h>
710ffe40b3SMatthew Dillon #include <sys/stat.h>
720ffe40b3SMatthew Dillon #include <sys/wait.h>
730ffe40b3SMatthew Dillon #define DKTYPENAMES
740ffe40b3SMatthew Dillon #include <sys/disklabel64.h>
750ffe40b3SMatthew Dillon #include <sys/diskslice.h>
760ffe40b3SMatthew Dillon #include <sys/diskmbr.h>
770ffe40b3SMatthew Dillon #include <sys/dtype.h>
780ffe40b3SMatthew Dillon #include <sys/sysctl.h>
790ffe40b3SMatthew Dillon #include <disktab.h>
802c3b1d1bSSascha Wildner #include <fcntl.h>
81d736a600SMatthew Dillon #include <fstab.h>
820ffe40b3SMatthew Dillon
830ffe40b3SMatthew Dillon #include <vfs/ufs/dinode.h>
840ffe40b3SMatthew Dillon #include <vfs/ufs/fs.h>
850ffe40b3SMatthew Dillon
860ffe40b3SMatthew Dillon #include <unistd.h>
870ffe40b3SMatthew Dillon #include <string.h>
880ffe40b3SMatthew Dillon #include <stdio.h>
890ffe40b3SMatthew Dillon #include <stdlib.h>
900ffe40b3SMatthew Dillon #include <signal.h>
910ffe40b3SMatthew Dillon #include <stdarg.h>
920ffe40b3SMatthew Dillon #include <stddef.h>
930ffe40b3SMatthew Dillon #include <ctype.h>
940ffe40b3SMatthew Dillon #include <err.h>
950ffe40b3SMatthew Dillon #include <errno.h>
960ffe40b3SMatthew Dillon #include <uuid.h>
970ffe40b3SMatthew Dillon #include "pathnames.h"
980ffe40b3SMatthew Dillon
990ffe40b3SMatthew Dillon extern uint32_t crc32(const void *buf, size_t size);
1000ffe40b3SMatthew Dillon
1010a319615SMatthew Dillon static void makelabel(const char *, const char *, struct disklabel64 *);
1020a319615SMatthew Dillon static int writelabel(int, struct disklabel64 *);
10335a9ab8aSMatthew Dillon static int expandlabel(int f, struct disklabel64 *lp, int *wbackp);
1040a319615SMatthew Dillon static void l_perror(const char *);
1050a319615SMatthew Dillon static void display(FILE *, const struct disklabel64 *);
1060a319615SMatthew Dillon static int edit(struct disklabel64 *, int);
1070a319615SMatthew Dillon static int editit(void);
1080a319615SMatthew Dillon static char *skip(char *);
1090a319615SMatthew Dillon static char *word(char *);
1100a319615SMatthew Dillon static int parse_field_val(char **, char **, u_int64_t *, int);
1110a319615SMatthew Dillon static int getasciilabel(FILE *, struct disklabel64 *);
1120a319615SMatthew Dillon static int getasciipartspec(char *, struct disklabel64 *, int, int, uint32_t);
1130a319615SMatthew Dillon static int getasciipartuuid(char *, struct disklabel64 *, int, int, uint32_t);
1140a319615SMatthew Dillon static int checklabel(struct disklabel64 *);
1150a319615SMatthew Dillon static void Warning(const char *, ...) __printflike(1, 2);
1160a319615SMatthew Dillon static void usage(void);
1170a319615SMatthew Dillon static struct disklabel64 *getvirginlabel(void);
1180a319615SMatthew Dillon static struct disklabel64 *readlabel(int);
1190a319615SMatthew Dillon static struct disklabel64 *makebootarea(int);
1200ffe40b3SMatthew Dillon
1210ffe40b3SMatthew Dillon #define DEFEDITOR _PATH_VI
1220ffe40b3SMatthew Dillon #define streq(a,b) (strcmp(a,b) == 0)
1230ffe40b3SMatthew Dillon
1240a319615SMatthew Dillon static char *dkname;
1250a319615SMatthew Dillon static char *specname;
1260a319615SMatthew Dillon static char tmpfil[] = PATH_TMPFILE;
1270ffe40b3SMatthew Dillon
1280a319615SMatthew Dillon static struct disklabel64 lab;
1290ffe40b3SMatthew Dillon
1300ffe40b3SMatthew Dillon #define MAX_PART ('z')
1310ffe40b3SMatthew Dillon #define MAX_NUM_PARTS (1 + MAX_PART - 'a')
1320a319615SMatthew Dillon static char part_size_type[MAX_NUM_PARTS];
1330a319615SMatthew Dillon static char part_offset_type[MAX_NUM_PARTS];
1340a319615SMatthew Dillon static int part_set[MAX_NUM_PARTS];
1350ffe40b3SMatthew Dillon
13635a9ab8aSMatthew Dillon static int installboot;
13735a9ab8aSMatthew Dillon static int expandopt;
1380a319615SMatthew Dillon static int boot1size;
1390a319615SMatthew Dillon static int boot1lsize;
1400a319615SMatthew Dillon static int boot2size;
1410a319615SMatthew Dillon static char *boot1buf;
1420a319615SMatthew Dillon static char *boot2buf;
1430a319615SMatthew Dillon static char *boot1path;
1440a319615SMatthew Dillon static char *boot2path;
1450ffe40b3SMatthew Dillon
1460a319615SMatthew Dillon static enum {
14735a9ab8aSMatthew Dillon UNSPEC, EDIT, NOWRITE, READ, RESTORE, WRITE, WRITEABLE, WRITEBOOT,
14835a9ab8aSMatthew Dillon EXPAND
1490ffe40b3SMatthew Dillon } op = UNSPEC;
1500ffe40b3SMatthew Dillon
1510a319615SMatthew Dillon static int rflag;
1520a319615SMatthew Dillon static int Vflag;
1530a319615SMatthew Dillon static int disable_write; /* set to disable writing to disk label */
1540ffe40b3SMatthew Dillon
1550ffe40b3SMatthew Dillon #ifdef DEBUG
1560a319615SMatthew Dillon static int debug;
15735a9ab8aSMatthew Dillon #define OPTIONS "BNRWb:denrs:Vwx"
1580ffe40b3SMatthew Dillon #else
15935a9ab8aSMatthew Dillon #define OPTIONS "BNRWb:enrs:Vwx"
1600ffe40b3SMatthew Dillon #endif
1610ffe40b3SMatthew Dillon
1620ffe40b3SMatthew Dillon int
main(int argc,char * argv[])1630ffe40b3SMatthew Dillon main(int argc, char *argv[])
1640ffe40b3SMatthew Dillon {
1650ffe40b3SMatthew Dillon struct disklabel64 *lp;
1660ffe40b3SMatthew Dillon FILE *t;
1670ffe40b3SMatthew Dillon int ch, f = 0, flag, error = 0;
1680a319615SMatthew Dillon const char *name = NULL;
1690a319615SMatthew Dillon const char *dtype = NULL;
1700ffe40b3SMatthew Dillon
1710ffe40b3SMatthew Dillon while ((ch = getopt(argc, argv, OPTIONS)) != -1)
1720ffe40b3SMatthew Dillon switch (ch) {
1730ffe40b3SMatthew Dillon case 'B':
1740ffe40b3SMatthew Dillon ++installboot;
1750ffe40b3SMatthew Dillon break;
1760ffe40b3SMatthew Dillon case 'b':
1770ffe40b3SMatthew Dillon boot1path = optarg;
1780ffe40b3SMatthew Dillon break;
1790ffe40b3SMatthew Dillon
1800ffe40b3SMatthew Dillon case 's':
1810ffe40b3SMatthew Dillon boot2path = optarg;
1820ffe40b3SMatthew Dillon break;
1830ffe40b3SMatthew Dillon case 'N':
1840ffe40b3SMatthew Dillon if (op != UNSPEC)
1850ffe40b3SMatthew Dillon usage();
1860ffe40b3SMatthew Dillon op = NOWRITE;
1870ffe40b3SMatthew Dillon break;
1880ffe40b3SMatthew Dillon case 'n':
1890ffe40b3SMatthew Dillon disable_write = 1;
1900ffe40b3SMatthew Dillon break;
1910ffe40b3SMatthew Dillon case 'R':
1920ffe40b3SMatthew Dillon if (op != UNSPEC)
1930ffe40b3SMatthew Dillon usage();
1940ffe40b3SMatthew Dillon op = RESTORE;
1950ffe40b3SMatthew Dillon break;
1960ffe40b3SMatthew Dillon case 'W':
1970ffe40b3SMatthew Dillon if (op != UNSPEC)
1980ffe40b3SMatthew Dillon usage();
1990ffe40b3SMatthew Dillon op = WRITEABLE;
2000ffe40b3SMatthew Dillon break;
2010ffe40b3SMatthew Dillon case 'e':
2020ffe40b3SMatthew Dillon if (op != UNSPEC)
2030ffe40b3SMatthew Dillon usage();
2040ffe40b3SMatthew Dillon op = EDIT;
2050ffe40b3SMatthew Dillon break;
2060ffe40b3SMatthew Dillon case 'V':
2070ffe40b3SMatthew Dillon ++Vflag;
2080ffe40b3SMatthew Dillon break;
2090ffe40b3SMatthew Dillon case 'r':
2100ffe40b3SMatthew Dillon ++rflag;
2110ffe40b3SMatthew Dillon break;
2120ffe40b3SMatthew Dillon case 'w':
2130ffe40b3SMatthew Dillon if (op != UNSPEC)
2140ffe40b3SMatthew Dillon usage();
2150ffe40b3SMatthew Dillon op = WRITE;
2160ffe40b3SMatthew Dillon break;
21735a9ab8aSMatthew Dillon case 'x':
21835a9ab8aSMatthew Dillon expandopt++;
21935a9ab8aSMatthew Dillon op = EXPAND;
22035a9ab8aSMatthew Dillon break;
2210ffe40b3SMatthew Dillon #ifdef DEBUG
2220ffe40b3SMatthew Dillon case 'd':
2230ffe40b3SMatthew Dillon debug++;
2240ffe40b3SMatthew Dillon break;
2250ffe40b3SMatthew Dillon #endif
2260ffe40b3SMatthew Dillon case '?':
2270ffe40b3SMatthew Dillon default:
2280ffe40b3SMatthew Dillon usage();
2290ffe40b3SMatthew Dillon }
2300ffe40b3SMatthew Dillon argc -= optind;
2310ffe40b3SMatthew Dillon argv += optind;
2320ffe40b3SMatthew Dillon if (installboot) {
2330ffe40b3SMatthew Dillon rflag++;
2340ffe40b3SMatthew Dillon if (op == UNSPEC)
2350ffe40b3SMatthew Dillon op = WRITEBOOT;
2360ffe40b3SMatthew Dillon } else {
2370ffe40b3SMatthew Dillon if (op == UNSPEC)
2380ffe40b3SMatthew Dillon op = READ;
2390ffe40b3SMatthew Dillon boot1path = NULL;
2400ffe40b3SMatthew Dillon boot2path = NULL;
2410ffe40b3SMatthew Dillon }
2420ffe40b3SMatthew Dillon if (argc < 1)
2430ffe40b3SMatthew Dillon usage();
2440ffe40b3SMatthew Dillon
245d736a600SMatthew Dillon dkname = getdevpath(argv[0], 0);
2460ffe40b3SMatthew Dillon specname = dkname;
2470ffe40b3SMatthew Dillon f = open(specname, op == READ ? O_RDONLY : O_RDWR);
2480ffe40b3SMatthew Dillon if (f < 0)
2490ffe40b3SMatthew Dillon err(4, "%s", specname);
2500ffe40b3SMatthew Dillon
2510ffe40b3SMatthew Dillon switch(op) {
2520ffe40b3SMatthew Dillon
2530ffe40b3SMatthew Dillon case UNSPEC:
2540ffe40b3SMatthew Dillon break;
2550ffe40b3SMatthew Dillon
2560ffe40b3SMatthew Dillon case EDIT:
2570ffe40b3SMatthew Dillon if (argc != 1)
2580ffe40b3SMatthew Dillon usage();
2590ffe40b3SMatthew Dillon lp = readlabel(f);
2600ffe40b3SMatthew Dillon error = edit(lp, f);
2610ffe40b3SMatthew Dillon break;
2620ffe40b3SMatthew Dillon
2630ffe40b3SMatthew Dillon case NOWRITE:
2640ffe40b3SMatthew Dillon flag = 0;
2650ffe40b3SMatthew Dillon if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0)
2660ffe40b3SMatthew Dillon err(4, "ioctl DIOCWLABEL");
2670ffe40b3SMatthew Dillon break;
2680ffe40b3SMatthew Dillon
2690ffe40b3SMatthew Dillon case READ:
2700ffe40b3SMatthew Dillon if (argc != 1)
2710ffe40b3SMatthew Dillon usage();
2720ffe40b3SMatthew Dillon lp = readlabel(f);
2730ffe40b3SMatthew Dillon display(stdout, lp);
2740ffe40b3SMatthew Dillon error = checklabel(lp);
2750ffe40b3SMatthew Dillon break;
2760ffe40b3SMatthew Dillon
27735a9ab8aSMatthew Dillon case EXPAND:
27835a9ab8aSMatthew Dillon {
27935a9ab8aSMatthew Dillon int wback = 0;
28035a9ab8aSMatthew Dillon
28135a9ab8aSMatthew Dillon lp = readlabel(f);
28235a9ab8aSMatthew Dillon error = expandlabel(f, lp, &wback);
28335a9ab8aSMatthew Dillon if (checklabel(lp) == 0 && wback)
28435a9ab8aSMatthew Dillon error = writelabel(f, lp);
28535a9ab8aSMatthew Dillon }
28635a9ab8aSMatthew Dillon break;
28735a9ab8aSMatthew Dillon
2880ffe40b3SMatthew Dillon case RESTORE:
2890ffe40b3SMatthew Dillon if (installboot && argc == 3) {
2900ffe40b3SMatthew Dillon makelabel(argv[2], 0, &lab);
2910ffe40b3SMatthew Dillon argc--;
2920ffe40b3SMatthew Dillon
2930ffe40b3SMatthew Dillon /*
2940ffe40b3SMatthew Dillon * We only called makelabel() for its side effect
2950ffe40b3SMatthew Dillon * of setting the bootstrap file names. Discard
2960ffe40b3SMatthew Dillon * all changes to `lab' so that all values in the
2970ffe40b3SMatthew Dillon * final label come from the ASCII label.
2980ffe40b3SMatthew Dillon */
2990ffe40b3SMatthew Dillon bzero((char *)&lab, sizeof(lab));
3000ffe40b3SMatthew Dillon }
3010ffe40b3SMatthew Dillon if (argc != 2)
3020ffe40b3SMatthew Dillon usage();
3030ffe40b3SMatthew Dillon if (!(t = fopen(argv[1], "r")))
3040ffe40b3SMatthew Dillon err(4, "%s", argv[1]);
3050ffe40b3SMatthew Dillon if (!getasciilabel(t, &lab))
3060ffe40b3SMatthew Dillon exit(1);
3070ffe40b3SMatthew Dillon lp = makebootarea(f);
3080ffe40b3SMatthew Dillon bcopy(&lab.d_magic, &lp->d_magic,
3090ffe40b3SMatthew Dillon sizeof(lab) - offsetof(struct disklabel64, d_magic));
3100ffe40b3SMatthew Dillon error = writelabel(f, lp);
3110ffe40b3SMatthew Dillon break;
3120ffe40b3SMatthew Dillon
3130ffe40b3SMatthew Dillon case WRITE:
3140ffe40b3SMatthew Dillon if (argc == 3) {
3150ffe40b3SMatthew Dillon name = argv[2];
3160ffe40b3SMatthew Dillon argc--;
3170ffe40b3SMatthew Dillon }
3180a319615SMatthew Dillon if (argc == 2)
3190a319615SMatthew Dillon dtype = argv[1];
3200a319615SMatthew Dillon else if (argc == 1)
3210a319615SMatthew Dillon dtype = "auto";
3220a319615SMatthew Dillon else
3230ffe40b3SMatthew Dillon usage();
3240a319615SMatthew Dillon makelabel(dtype, name, &lab);
3250ffe40b3SMatthew Dillon lp = makebootarea(f);
3260ffe40b3SMatthew Dillon bcopy(&lab.d_magic, &lp->d_magic,
3270ffe40b3SMatthew Dillon sizeof(lab) - offsetof(struct disklabel64, d_magic));
3280ffe40b3SMatthew Dillon if (checklabel(lp) == 0)
3290ffe40b3SMatthew Dillon error = writelabel(f, lp);
3300ffe40b3SMatthew Dillon break;
3310ffe40b3SMatthew Dillon
3320ffe40b3SMatthew Dillon case WRITEABLE:
3330ffe40b3SMatthew Dillon flag = 1;
3340ffe40b3SMatthew Dillon if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0)
3350ffe40b3SMatthew Dillon err(4, "ioctl DIOCWLABEL");
3360ffe40b3SMatthew Dillon break;
3370ffe40b3SMatthew Dillon
3380ffe40b3SMatthew Dillon case WRITEBOOT:
3390ffe40b3SMatthew Dillon {
3400ffe40b3SMatthew Dillon struct disklabel64 tlab;
3410ffe40b3SMatthew Dillon
3420ffe40b3SMatthew Dillon lp = readlabel(f);
3430ffe40b3SMatthew Dillon tlab = *lp;
3440ffe40b3SMatthew Dillon if (argc == 2)
3450ffe40b3SMatthew Dillon makelabel(argv[1], 0, &lab);
3460ffe40b3SMatthew Dillon lp = makebootarea(f);
3470ffe40b3SMatthew Dillon bcopy(&tlab.d_magic, &lp->d_magic,
3480ffe40b3SMatthew Dillon sizeof(tlab) - offsetof(struct disklabel64, d_magic));
3490ffe40b3SMatthew Dillon if (checklabel(lp) == 0)
3500ffe40b3SMatthew Dillon error = writelabel(f, lp);
3510ffe40b3SMatthew Dillon break;
3520ffe40b3SMatthew Dillon }
3530ffe40b3SMatthew Dillon }
3540ffe40b3SMatthew Dillon exit(error);
3550ffe40b3SMatthew Dillon }
3560ffe40b3SMatthew Dillon
3570ffe40b3SMatthew Dillon /*
3580ffe40b3SMatthew Dillon * Construct a prototype disklabel from /etc/disktab. As a side
3590ffe40b3SMatthew Dillon * effect, set the names of the primary and secondary boot files
3600ffe40b3SMatthew Dillon * if specified.
3610ffe40b3SMatthew Dillon */
3620a319615SMatthew Dillon static void
makelabel(const char * type,const char * name,struct disklabel64 * lp)3630ffe40b3SMatthew Dillon makelabel(const char *type, const char *name, struct disklabel64 *lp)
3640ffe40b3SMatthew Dillon {
3650ffe40b3SMatthew Dillon struct disklabel64 *dp;
3660ffe40b3SMatthew Dillon
36787b121bbSAaron LI if (streq(type, "auto"))
3680ffe40b3SMatthew Dillon dp = getvirginlabel();
3690ffe40b3SMatthew Dillon else
3700a319615SMatthew Dillon errx(1, "no disktab(5) support yet; only 'auto' allowed");
3710ffe40b3SMatthew Dillon *lp = *dp;
3720ffe40b3SMatthew Dillon
3730ffe40b3SMatthew Dillon if (name)
3740a319615SMatthew Dillon strlcpy((char *)lp->d_packname, name, sizeof(lp->d_packname));
3750ffe40b3SMatthew Dillon }
3760ffe40b3SMatthew Dillon
3770a319615SMatthew Dillon static int
writelabel(int f,struct disklabel64 * lp)3780ffe40b3SMatthew Dillon writelabel(int f, struct disklabel64 *lp)
3790ffe40b3SMatthew Dillon {
3800ffe40b3SMatthew Dillon struct disklabel64 *blp;
3810ffe40b3SMatthew Dillon int flag;
3820ffe40b3SMatthew Dillon int r;
3830ffe40b3SMatthew Dillon size_t lpsize;
3840ffe40b3SMatthew Dillon size_t lpcrcsize;
3850ffe40b3SMatthew Dillon
3860ffe40b3SMatthew Dillon lpsize = offsetof(struct disklabel64, d_partitions[lp->d_npartitions]);
3870ffe40b3SMatthew Dillon lpcrcsize = lpsize - offsetof(struct disklabel64, d_magic);
3880ffe40b3SMatthew Dillon
3890ffe40b3SMatthew Dillon if (disable_write) {
3900ca0cd25SSascha Wildner Warning("write to disk label suppressed - label was as follows:");
3910ffe40b3SMatthew Dillon display(stdout, lp);
3920ffe40b3SMatthew Dillon return (0);
3930ffe40b3SMatthew Dillon } else {
3940ffe40b3SMatthew Dillon lp->d_magic = DISKMAGIC64;
3950ffe40b3SMatthew Dillon lp->d_crc = 0;
3960ffe40b3SMatthew Dillon lp->d_crc = crc32(&lp->d_magic, lpcrcsize);
3970ffe40b3SMatthew Dillon if (rflag) {
3980ffe40b3SMatthew Dillon /*
3990ffe40b3SMatthew Dillon * Make sure the boot area is not too large
4000ffe40b3SMatthew Dillon */
4010ffe40b3SMatthew Dillon if (boot2buf) {
4020ffe40b3SMatthew Dillon int lpbsize = (int)(lp->d_pbase - lp->d_bbase);
4030ffe40b3SMatthew Dillon if (lp->d_pbase == 0) {
4040ffe40b3SMatthew Dillon errx(1, "no space was set aside in "
4050ffe40b3SMatthew Dillon "the disklabel for boot2!");
4060ffe40b3SMatthew Dillon }
4070ffe40b3SMatthew Dillon if (boot2size > lpbsize) {
4080ffe40b3SMatthew Dillon errx(1, "label did not reserve enough "
4090ffe40b3SMatthew Dillon "space for boot! %d/%d",
4100ffe40b3SMatthew Dillon boot2size, lpbsize);
4110ffe40b3SMatthew Dillon }
4120ffe40b3SMatthew Dillon }
4130ffe40b3SMatthew Dillon
4140ffe40b3SMatthew Dillon /*
4150ffe40b3SMatthew Dillon * First set the kernel disk label,
4160ffe40b3SMatthew Dillon * then write a label to the raw disk.
4170ffe40b3SMatthew Dillon * If the SDINFO ioctl fails because it is
4180ffe40b3SMatthew Dillon * unimplemented, keep going; otherwise, the kernel
4190ffe40b3SMatthew Dillon * consistency checks may prevent us from changing
4200ffe40b3SMatthew Dillon * the current (in-core) label.
4210ffe40b3SMatthew Dillon */
4220ffe40b3SMatthew Dillon if (ioctl(f, DIOCSDINFO64, lp) < 0 &&
4230ffe40b3SMatthew Dillon errno != ENODEV && errno != ENOTTY) {
4240ffe40b3SMatthew Dillon l_perror("ioctl DIOCSDINFO");
4250ffe40b3SMatthew Dillon return (1);
4260ffe40b3SMatthew Dillon }
4270ffe40b3SMatthew Dillon lseek(f, (off_t)0, SEEK_SET);
4280ffe40b3SMatthew Dillon
4290ffe40b3SMatthew Dillon /*
4300ffe40b3SMatthew Dillon * The disklabel embeds areas which we may not
4310ffe40b3SMatthew Dillon * have wanted to change. Merge those areas in
4320ffe40b3SMatthew Dillon * from disk.
4330ffe40b3SMatthew Dillon */
4340ffe40b3SMatthew Dillon blp = makebootarea(f);
4350ffe40b3SMatthew Dillon if (blp != lp) {
4360ffe40b3SMatthew Dillon bcopy(&lp->d_magic, &blp->d_magic,
4370ffe40b3SMatthew Dillon sizeof(*lp) -
4380ffe40b3SMatthew Dillon offsetof(struct disklabel64, d_magic));
4390ffe40b3SMatthew Dillon }
4400ffe40b3SMatthew Dillon
4410ffe40b3SMatthew Dillon /*
4420ffe40b3SMatthew Dillon * write enable label sector before write
4430ffe40b3SMatthew Dillon * (if necessary), disable after writing.
4440ffe40b3SMatthew Dillon */
4450ffe40b3SMatthew Dillon flag = 1;
4460ffe40b3SMatthew Dillon if (ioctl(f, DIOCWLABEL, &flag) < 0)
4470ffe40b3SMatthew Dillon warn("ioctl DIOCWLABEL");
4480ffe40b3SMatthew Dillon
4490ffe40b3SMatthew Dillon r = write(f, boot1buf, boot1lsize);
4500ffe40b3SMatthew Dillon if (r != (ssize_t)boot1lsize) {
4510ffe40b3SMatthew Dillon warn("write");
4520ffe40b3SMatthew Dillon return (1);
4530ffe40b3SMatthew Dillon }
4540ffe40b3SMatthew Dillon /*
4550ffe40b3SMatthew Dillon * Output the remainder of the disklabel
4560ffe40b3SMatthew Dillon */
4570ffe40b3SMatthew Dillon if (boot2buf) {
4580ffe40b3SMatthew Dillon lseek(f, lp->d_bbase, 0);
4590ffe40b3SMatthew Dillon r = write(f, boot2buf, boot2size);
4600ffe40b3SMatthew Dillon if (r != boot2size) {
4610ffe40b3SMatthew Dillon warn("write");
4620ffe40b3SMatthew Dillon return(1);
4630ffe40b3SMatthew Dillon }
4640ffe40b3SMatthew Dillon }
4650ffe40b3SMatthew Dillon flag = 0;
4660ffe40b3SMatthew Dillon ioctl(f, DIOCWLABEL, &flag);
4670ffe40b3SMatthew Dillon } else if (ioctl(f, DIOCWDINFO64, lp) < 0) {
4680ffe40b3SMatthew Dillon l_perror("ioctl DIOCWDINFO64");
4690ffe40b3SMatthew Dillon return (1);
4700ffe40b3SMatthew Dillon }
4710ffe40b3SMatthew Dillon }
4720ffe40b3SMatthew Dillon return (0);
4730ffe40b3SMatthew Dillon }
4740ffe40b3SMatthew Dillon
4750a319615SMatthew Dillon static void
l_perror(const char * s)4760ffe40b3SMatthew Dillon l_perror(const char *s)
4770ffe40b3SMatthew Dillon {
4780ffe40b3SMatthew Dillon switch (errno) {
4790ffe40b3SMatthew Dillon
4800ffe40b3SMatthew Dillon case ESRCH:
4810ffe40b3SMatthew Dillon warnx("%s: no disk label on disk;", s);
4820ffe40b3SMatthew Dillon fprintf(stderr, "add \"-r\" to install initial label\n");
4830ffe40b3SMatthew Dillon break;
4840ffe40b3SMatthew Dillon
4850ffe40b3SMatthew Dillon case EINVAL:
4860ffe40b3SMatthew Dillon warnx("%s: label magic number or checksum is wrong!", s);
4870ffe40b3SMatthew Dillon fprintf(stderr, "(disklabel or kernel is out of date?)\n");
4880ffe40b3SMatthew Dillon break;
4890ffe40b3SMatthew Dillon
4900ffe40b3SMatthew Dillon case EBUSY:
4910ffe40b3SMatthew Dillon warnx("%s: open partition would move or shrink", s);
4920ffe40b3SMatthew Dillon break;
4930ffe40b3SMatthew Dillon
4940ffe40b3SMatthew Dillon case ENOATTR:
4950ffe40b3SMatthew Dillon warnx("%s: the disk already has a label of a different type,\n"
4960ffe40b3SMatthew Dillon "probably a 32 bit disklabel. It must be cleaned out "
4970ffe40b3SMatthew Dillon "first.\n", s);
4980ffe40b3SMatthew Dillon break;
4990ffe40b3SMatthew Dillon
5000ffe40b3SMatthew Dillon default:
5012038fb68SSascha Wildner warn(NULL);
5020ffe40b3SMatthew Dillon break;
5030ffe40b3SMatthew Dillon }
5040ffe40b3SMatthew Dillon }
5050ffe40b3SMatthew Dillon
5060ffe40b3SMatthew Dillon /*
5070ffe40b3SMatthew Dillon * Fetch disklabel for disk.
5080ffe40b3SMatthew Dillon * Use ioctl to get label unless -r flag is given.
5090ffe40b3SMatthew Dillon */
5100a319615SMatthew Dillon static struct disklabel64 *
readlabel(int f)5110ffe40b3SMatthew Dillon readlabel(int f)
5120ffe40b3SMatthew Dillon {
5130ffe40b3SMatthew Dillon struct disklabel64 *lp;
5140ffe40b3SMatthew Dillon u_int32_t savecrc;
5150ffe40b3SMatthew Dillon size_t lpcrcsize;
5160ffe40b3SMatthew Dillon
5170ffe40b3SMatthew Dillon if (rflag) {
5180ffe40b3SMatthew Dillon /*
5190ffe40b3SMatthew Dillon * Allocate space for the label. The boot1 code, if any,
5200ffe40b3SMatthew Dillon * is embedded in the label. The label overlaps the boot1
5210ffe40b3SMatthew Dillon * code.
5220ffe40b3SMatthew Dillon */
5230ffe40b3SMatthew Dillon lp = makebootarea(f);
5240ffe40b3SMatthew Dillon lpcrcsize = offsetof(struct disklabel64,
5250ffe40b3SMatthew Dillon d_partitions[lp->d_npartitions]) -
5260ffe40b3SMatthew Dillon offsetof(struct disklabel64, d_magic);
5270ffe40b3SMatthew Dillon savecrc = lp->d_crc;
5280ffe40b3SMatthew Dillon lp->d_crc = 0;
5290ffe40b3SMatthew Dillon if (lp->d_magic != DISKMAGIC64)
5300ffe40b3SMatthew Dillon errx(1, "bad pack magic number");
5310ffe40b3SMatthew Dillon if (lp->d_npartitions > MAXPARTITIONS64 ||
5320ffe40b3SMatthew Dillon savecrc != crc32(&lp->d_magic, lpcrcsize)
5330ffe40b3SMatthew Dillon ) {
5340ffe40b3SMatthew Dillon errx(1, "corrupted disklabel64");
5350ffe40b3SMatthew Dillon }
5360ffe40b3SMatthew Dillon lp->d_crc = savecrc;
5370ffe40b3SMatthew Dillon } else {
5380ffe40b3SMatthew Dillon /*
5390ffe40b3SMatthew Dillon * Just use a static structure to hold the label. Note
5400ffe40b3SMatthew Dillon * that DIOCSDINFO64 does not overwrite the boot1 area
5410ffe40b3SMatthew Dillon * even though it is part of the disklabel64 structure.
5420ffe40b3SMatthew Dillon */
5430ffe40b3SMatthew Dillon lp = &lab;
5440ffe40b3SMatthew Dillon if (Vflag) {
5450ffe40b3SMatthew Dillon if (ioctl(f, DIOCGDVIRGIN64, lp) < 0) {
5460ffe40b3SMatthew Dillon l_perror("ioctl DIOCGDVIRGIN64");
5470ffe40b3SMatthew Dillon exit(4);
5480ffe40b3SMatthew Dillon }
5490ffe40b3SMatthew Dillon } else {
5500ffe40b3SMatthew Dillon if (ioctl(f, DIOCGDINFO64, lp) < 0) {
5510ffe40b3SMatthew Dillon l_perror("ioctl DIOCGDINFO64");
5520ffe40b3SMatthew Dillon exit(4);
5530ffe40b3SMatthew Dillon }
5540ffe40b3SMatthew Dillon }
5550ffe40b3SMatthew Dillon }
5560ffe40b3SMatthew Dillon return (lp);
5570ffe40b3SMatthew Dillon }
5580ffe40b3SMatthew Dillon
5590ffe40b3SMatthew Dillon /*
5600ffe40b3SMatthew Dillon * Construct a boot area for boot1 and boot2 and return the location of
5610ffe40b3SMatthew Dillon * the label within the area. The caller will overwrite the label so
5620ffe40b3SMatthew Dillon * we don't actually have to read it.
5630ffe40b3SMatthew Dillon */
5640a319615SMatthew Dillon static struct disklabel64 *
makebootarea(int f)5650ffe40b3SMatthew Dillon makebootarea(int f)
5660ffe40b3SMatthew Dillon {
5670ffe40b3SMatthew Dillon struct disklabel64 *lp;
5680ffe40b3SMatthew Dillon struct partinfo info;
5690ffe40b3SMatthew Dillon u_int32_t secsize;
5700ffe40b3SMatthew Dillon struct stat st;
5710ffe40b3SMatthew Dillon int fd;
5720ffe40b3SMatthew Dillon int r;
5730ffe40b3SMatthew Dillon
5740ffe40b3SMatthew Dillon if (ioctl(f, DIOCGPART, &info) == 0)
5750ffe40b3SMatthew Dillon secsize = info.media_blksize;
5760ffe40b3SMatthew Dillon else
5770ffe40b3SMatthew Dillon secsize = 512;
5780ffe40b3SMatthew Dillon
5790ffe40b3SMatthew Dillon if (boot1buf == NULL) {
5800ffe40b3SMatthew Dillon size_t rsize;
5810ffe40b3SMatthew Dillon
582965b839fSSascha Wildner rsize = roundup2(sizeof(struct disklabel64), secsize);
5830ffe40b3SMatthew Dillon boot1size = offsetof(struct disklabel64, d_magic);
5840ffe40b3SMatthew Dillon boot1lsize = rsize;
5850ffe40b3SMatthew Dillon boot1buf = malloc(rsize);
5860ffe40b3SMatthew Dillon bzero(boot1buf, rsize);
5870ffe40b3SMatthew Dillon r = read(f, boot1buf, rsize);
5880a319615SMatthew Dillon if (r != (int)rsize) {
5890a319615SMatthew Dillon free(boot1buf);
5900ffe40b3SMatthew Dillon err(4, "%s", specname);
5910ffe40b3SMatthew Dillon }
5920a319615SMatthew Dillon }
5930ffe40b3SMatthew Dillon lp = (void *)boot1buf;
5940ffe40b3SMatthew Dillon
5950ffe40b3SMatthew Dillon if (installboot == 0)
5960ffe40b3SMatthew Dillon return(lp);
5970ffe40b3SMatthew Dillon
5980ffe40b3SMatthew Dillon if (boot2buf == NULL) {
5990a319615SMatthew Dillon boot2size = BOOT2SIZE64;
6000ffe40b3SMatthew Dillon boot2buf = malloc(boot2size);
6010ffe40b3SMatthew Dillon bzero(boot2buf, boot2size);
6020ffe40b3SMatthew Dillon }
6030ffe40b3SMatthew Dillon
6040ffe40b3SMatthew Dillon /*
6050ffe40b3SMatthew Dillon * If installing the boot code, read it into the appropriate portions
6060ffe40b3SMatthew Dillon * of the buffer(s)
6070ffe40b3SMatthew Dillon */
6080ffe40b3SMatthew Dillon if (boot1path == NULL)
6090ffe40b3SMatthew Dillon asprintf(&boot1path, "%s/boot1_64", _PATH_BOOTDIR);
6100ffe40b3SMatthew Dillon if (boot2path == NULL)
6110ffe40b3SMatthew Dillon asprintf(&boot2path, "%s/boot2_64", _PATH_BOOTDIR);
6120ffe40b3SMatthew Dillon
6130ffe40b3SMatthew Dillon if ((fd = open(boot1path, O_RDONLY)) < 0)
6140ffe40b3SMatthew Dillon err(4, "%s", boot1path);
6150ffe40b3SMatthew Dillon if (fstat(fd, &st) < 0)
6160ffe40b3SMatthew Dillon err(4, "%s", boot1path);
6170ffe40b3SMatthew Dillon if (st.st_size > boot1size)
6180ffe40b3SMatthew Dillon err(4, "%s must be exactly %d bytes!", boot1path, boot1size);
6190ffe40b3SMatthew Dillon if (read(fd, boot1buf, boot1size) != boot1size)
6200ffe40b3SMatthew Dillon err(4, "%s must be exactly %d bytes!", boot1path, boot1size);
6210ffe40b3SMatthew Dillon close(fd);
6220ffe40b3SMatthew Dillon
6230ffe40b3SMatthew Dillon if ((fd = open(boot2path, O_RDONLY)) < 0)
6240ffe40b3SMatthew Dillon err(4, "%s", boot2path);
6250ffe40b3SMatthew Dillon if (fstat(fd, &st) < 0)
6260ffe40b3SMatthew Dillon err(4, "%s", boot2path);
6270ffe40b3SMatthew Dillon if (st.st_size > boot2size)
6280ffe40b3SMatthew Dillon err(4, "%s must be <= %d bytes!", boot2path, boot2size);
6290ffe40b3SMatthew Dillon if ((r = read(fd, boot2buf, boot2size)) < 1)
6300ffe40b3SMatthew Dillon err(4, "%s is empty!", boot2path);
631965b839fSSascha Wildner boot2size = roundup2(r, secsize);
6320ffe40b3SMatthew Dillon close(fd);
6330ffe40b3SMatthew Dillon
6340ffe40b3SMatthew Dillon /*
6350ffe40b3SMatthew Dillon * XXX dangerously dedicated support goes here XXX
6360ffe40b3SMatthew Dillon */
6370ffe40b3SMatthew Dillon return (lp);
6380ffe40b3SMatthew Dillon }
6390ffe40b3SMatthew Dillon
6400a319615SMatthew Dillon static void
display(FILE * f,const struct disklabel64 * lp)6410ffe40b3SMatthew Dillon display(FILE *f, const struct disklabel64 *lp)
6420ffe40b3SMatthew Dillon {
6430ffe40b3SMatthew Dillon const struct partition64 *pp;
6440ffe40b3SMatthew Dillon char *str;
6450ffe40b3SMatthew Dillon unsigned int part;
6460ffe40b3SMatthew Dillon int didany;
6470ffe40b3SMatthew Dillon uint32_t blksize;
6480ffe40b3SMatthew Dillon
6490ffe40b3SMatthew Dillon /*
6500ffe40b3SMatthew Dillon * Use a human readable block size if possible. This is for
6510ffe40b3SMatthew Dillon * display and editing purposes only.
6520ffe40b3SMatthew Dillon */
6530ffe40b3SMatthew Dillon if (lp->d_align > 1024)
6540ffe40b3SMatthew Dillon blksize = 1024;
6550ffe40b3SMatthew Dillon else
6560ffe40b3SMatthew Dillon blksize = lp->d_align;
6570ffe40b3SMatthew Dillon
6580ffe40b3SMatthew Dillon fprintf(f, "# %s:\n", specname);
6590ffe40b3SMatthew Dillon fprintf(f, "#\n");
6600a319615SMatthew Dillon fprintf(f, "# Calculated informational fields for the slice:\n");
6610ffe40b3SMatthew Dillon fprintf(f, "#\n");
662a276dc6bSMatthew Dillon fprintf(f, "# boot space: %10ju bytes\n",
6631f5e0b99SSascha Wildner (uintmax_t)(lp->d_pbase - lp->d_bbase));
664a276dc6bSMatthew Dillon fprintf(f, "# data space: %10ju blocks\t# %6.2f MB (%ju bytes)\n",
6651f5e0b99SSascha Wildner (uintmax_t)(lp->d_pstop - lp->d_pbase) / blksize,
6660ffe40b3SMatthew Dillon (double)(lp->d_pstop - lp->d_pbase) / 1024.0 / 1024.0,
6671f5e0b99SSascha Wildner (uintmax_t)(lp->d_pstop - lp->d_pbase));
6680ffe40b3SMatthew Dillon fprintf(f, "#\n");
6690a319615SMatthew Dillon fprintf(f, "# NOTE: The partition data base and stop are physically\n");
6700a319615SMatthew Dillon fprintf(f, "# aligned instead of slice-relative aligned.\n");
6710a319615SMatthew Dillon fprintf(f, "#\n");
6720a319615SMatthew Dillon fprintf(f, "# All byte equivalent offsets must be aligned.\n");
6735179f0c5SMatthew Dillon fprintf(f, "#\n");
6740ffe40b3SMatthew Dillon
675529d55c9SMatthew Dillon uuid_to_string(&lp->d_stor_uuid, &str, NULL);
6760ffe40b3SMatthew Dillon fprintf(f, "diskid: %s\n", str ? str : "<unknown>");
6770ffe40b3SMatthew Dillon free(str);
6780ffe40b3SMatthew Dillon
6790a319615SMatthew Dillon fprintf(f, "label: %s\n", lp->d_packname);
6801f5e0b99SSascha Wildner fprintf(f, "boot2 data base: 0x%012jx\n", (uintmax_t)lp->d_bbase);
6811f5e0b99SSascha Wildner fprintf(f, "partitions data base: 0x%012jx\n", (uintmax_t)lp->d_pbase);
6821f5e0b99SSascha Wildner fprintf(f, "partitions data stop: 0x%012jx\n", (uintmax_t)lp->d_pstop);
6831f5e0b99SSascha Wildner fprintf(f, "backup label: 0x%012jx\n", (uintmax_t)lp->d_abase);
684a276dc6bSMatthew Dillon fprintf(f, "total size: 0x%012jx\t# %6.2f MB\n",
6851f5e0b99SSascha Wildner (uintmax_t)lp->d_total_size,
6860ffe40b3SMatthew Dillon (double)lp->d_total_size / 1024.0 / 1024.0);
6870ffe40b3SMatthew Dillon fprintf(f, "alignment: %u\n", lp->d_align);
6880a319615SMatthew Dillon fprintf(f, "display block size: %u\t# for partition display and edit only\n",
6890ffe40b3SMatthew Dillon blksize);
6900ffe40b3SMatthew Dillon
6910ffe40b3SMatthew Dillon fprintf(f, "\n");
6920ffe40b3SMatthew Dillon fprintf(f, "%u partitions:\n", lp->d_npartitions);
6930ffe40b3SMatthew Dillon fprintf(f, "# size offset fstype fsuuid\n");
6940ffe40b3SMatthew Dillon didany = 0;
695529d55c9SMatthew Dillon for (part = 0; part < lp->d_npartitions; part++) {
696529d55c9SMatthew Dillon pp = &lp->d_partitions[part];
6970ffe40b3SMatthew Dillon const u_long onemeg = 1024 * 1024;
698529d55c9SMatthew Dillon
6990ffe40b3SMatthew Dillon if (pp->p_bsize == 0)
7000ffe40b3SMatthew Dillon continue;
7010ffe40b3SMatthew Dillon didany = 1;
7020ffe40b3SMatthew Dillon fprintf(f, " %c: ", 'a' + part);
7030ffe40b3SMatthew Dillon
7040ffe40b3SMatthew Dillon if (pp->p_bsize % lp->d_align)
7050ffe40b3SMatthew Dillon fprintf(f, "%10s ", "ILLEGAL");
7060ffe40b3SMatthew Dillon else
7071f5e0b99SSascha Wildner fprintf(f, "%10ju ", (uintmax_t)pp->p_bsize / blksize);
7085179f0c5SMatthew Dillon
7095179f0c5SMatthew Dillon if ((pp->p_boffset - lp->d_pbase) % lp->d_align)
7100ffe40b3SMatthew Dillon fprintf(f, "%10s ", "ILLEGAL");
7110ffe40b3SMatthew Dillon else
712a276dc6bSMatthew Dillon fprintf(f, "%10ju ",
7131f5e0b99SSascha Wildner (uintmax_t)(pp->p_boffset - lp->d_pbase) / blksize);
7145179f0c5SMatthew Dillon
7150ffe40b3SMatthew Dillon if (pp->p_fstype < FSMAXTYPES)
7160ffe40b3SMatthew Dillon fprintf(f, "%8.8s", fstypenames[pp->p_fstype]);
7170ffe40b3SMatthew Dillon else
7180ffe40b3SMatthew Dillon fprintf(f, "%8d", pp->p_fstype);
71980818344SThomas Nikolajsen fprintf(f, "\t# %11.3fMB", (double)pp->p_bsize / onemeg);
7200ffe40b3SMatthew Dillon fprintf(f, "\n");
7210ffe40b3SMatthew Dillon }
722529d55c9SMatthew Dillon for (part = 0; part < lp->d_npartitions; part++) {
723529d55c9SMatthew Dillon pp = &lp->d_partitions[part];
724529d55c9SMatthew Dillon
725529d55c9SMatthew Dillon if (pp->p_bsize == 0)
726529d55c9SMatthew Dillon continue;
727529d55c9SMatthew Dillon
728529d55c9SMatthew Dillon if (uuid_is_nil(&lp->d_stor_uuid, NULL) == 0) {
729529d55c9SMatthew Dillon fprintf(f, " %c-stor_uuid: ", 'a' + part);
730529d55c9SMatthew Dillon str = NULL;
731529d55c9SMatthew Dillon uuid_to_string(&pp->p_stor_uuid, &str, NULL);
732529d55c9SMatthew Dillon if (str) {
733529d55c9SMatthew Dillon fprintf(f, "%s", str);
734529d55c9SMatthew Dillon free(str);
735529d55c9SMatthew Dillon }
736529d55c9SMatthew Dillon fprintf(f, "\n");
737529d55c9SMatthew Dillon }
738529d55c9SMatthew Dillon }
7390ffe40b3SMatthew Dillon if (didany == 0) {
7400ffe40b3SMatthew Dillon fprintf(f, "# EXAMPLE\n");
7410ffe40b3SMatthew Dillon fprintf(f, "#a: 4g 0 4.2BSD\n");
742529d55c9SMatthew Dillon fprintf(f, "#a: * * 4.2BSD\n");
7430ffe40b3SMatthew Dillon
7440ffe40b3SMatthew Dillon }
7450ffe40b3SMatthew Dillon fflush(f);
7460ffe40b3SMatthew Dillon }
7470ffe40b3SMatthew Dillon
7480a319615SMatthew Dillon static int
edit(struct disklabel64 * lp,int f)7490ffe40b3SMatthew Dillon edit(struct disklabel64 *lp, int f)
7500ffe40b3SMatthew Dillon {
7510ffe40b3SMatthew Dillon int c, fd;
7520ffe40b3SMatthew Dillon struct disklabel64 label;
7530ffe40b3SMatthew Dillon FILE *fp;
7540ffe40b3SMatthew Dillon
7550ffe40b3SMatthew Dillon if ((fd = mkstemp(tmpfil)) == -1 ||
7560ffe40b3SMatthew Dillon (fp = fdopen(fd, "w")) == NULL) {
7570ffe40b3SMatthew Dillon warnx("can't create %s", tmpfil);
7580ffe40b3SMatthew Dillon return (1);
7590ffe40b3SMatthew Dillon }
7600ffe40b3SMatthew Dillon display(fp, lp);
7610ffe40b3SMatthew Dillon fclose(fp);
7620ffe40b3SMatthew Dillon for (;;) {
7630ffe40b3SMatthew Dillon if (!editit())
7640ffe40b3SMatthew Dillon break;
7650ffe40b3SMatthew Dillon fp = fopen(tmpfil, "r");
7660ffe40b3SMatthew Dillon if (fp == NULL) {
7670ffe40b3SMatthew Dillon warnx("can't reopen %s for reading", tmpfil);
7680ffe40b3SMatthew Dillon break;
7690ffe40b3SMatthew Dillon }
7700ffe40b3SMatthew Dillon bzero((char *)&label, sizeof(label));
7710ffe40b3SMatthew Dillon if (getasciilabel(fp, &label)) {
7720ffe40b3SMatthew Dillon *lp = label;
7730ffe40b3SMatthew Dillon if (writelabel(f, lp) == 0) {
7740ffe40b3SMatthew Dillon fclose(fp);
7750ffe40b3SMatthew Dillon unlink(tmpfil);
7760ffe40b3SMatthew Dillon return (0);
7770ffe40b3SMatthew Dillon }
7780ffe40b3SMatthew Dillon }
7790ffe40b3SMatthew Dillon fclose(fp);
7800ffe40b3SMatthew Dillon printf("re-edit the label? [y]: "); fflush(stdout);
7810ffe40b3SMatthew Dillon c = getchar();
7820ffe40b3SMatthew Dillon if (c != EOF && c != (int)'\n')
7830ffe40b3SMatthew Dillon while (getchar() != (int)'\n')
7840ffe40b3SMatthew Dillon ;
7850ffe40b3SMatthew Dillon if (c == (int)'n')
7860ffe40b3SMatthew Dillon break;
7870ffe40b3SMatthew Dillon }
7880ffe40b3SMatthew Dillon unlink(tmpfil);
7890ffe40b3SMatthew Dillon return (1);
7900ffe40b3SMatthew Dillon }
7910ffe40b3SMatthew Dillon
7920a319615SMatthew Dillon static int
editit(void)7930ffe40b3SMatthew Dillon editit(void)
7940ffe40b3SMatthew Dillon {
7950ffe40b3SMatthew Dillon int pid, xpid;
7960ffe40b3SMatthew Dillon int status, omask;
7970ffe40b3SMatthew Dillon const char *ed;
7980ffe40b3SMatthew Dillon
7990ffe40b3SMatthew Dillon omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
8000ffe40b3SMatthew Dillon while ((pid = fork()) < 0) {
8010ffe40b3SMatthew Dillon if (errno == EPROCLIM) {
8020ffe40b3SMatthew Dillon warnx("you have too many processes");
8030ffe40b3SMatthew Dillon return(0);
8040ffe40b3SMatthew Dillon }
8050ffe40b3SMatthew Dillon if (errno != EAGAIN) {
8060ffe40b3SMatthew Dillon warn("fork");
8070ffe40b3SMatthew Dillon return(0);
8080ffe40b3SMatthew Dillon }
8090ffe40b3SMatthew Dillon sleep(1);
8100ffe40b3SMatthew Dillon }
8110ffe40b3SMatthew Dillon if (pid == 0) {
8120ffe40b3SMatthew Dillon sigsetmask(omask);
8130ffe40b3SMatthew Dillon setgid(getgid());
8140ffe40b3SMatthew Dillon setuid(getuid());
81560233e58SSascha Wildner if ((ed = getenv("EDITOR")) == NULL)
8160ffe40b3SMatthew Dillon ed = DEFEDITOR;
81760233e58SSascha Wildner execlp(ed, ed, tmpfil, NULL);
8180ffe40b3SMatthew Dillon err(1, "%s", ed);
8190ffe40b3SMatthew Dillon }
8200ffe40b3SMatthew Dillon while ((xpid = wait(&status)) >= 0)
8210ffe40b3SMatthew Dillon if (xpid == pid)
8220ffe40b3SMatthew Dillon break;
8230ffe40b3SMatthew Dillon sigsetmask(omask);
8240ffe40b3SMatthew Dillon return(!status);
8250ffe40b3SMatthew Dillon }
8260ffe40b3SMatthew Dillon
8270a319615SMatthew Dillon static char *
skip(char * cp)8280ffe40b3SMatthew Dillon skip(char *cp)
8290ffe40b3SMatthew Dillon {
8300ffe40b3SMatthew Dillon
8310ffe40b3SMatthew Dillon while (*cp != '\0' && isspace(*cp))
8320ffe40b3SMatthew Dillon cp++;
8330ffe40b3SMatthew Dillon if (*cp == '\0' || *cp == '#')
8340ffe40b3SMatthew Dillon return (NULL);
8350ffe40b3SMatthew Dillon return (cp);
8360ffe40b3SMatthew Dillon }
8370ffe40b3SMatthew Dillon
8380a319615SMatthew Dillon static char *
word(char * cp)8390ffe40b3SMatthew Dillon word(char *cp)
8400ffe40b3SMatthew Dillon {
8410ffe40b3SMatthew Dillon char c;
8420ffe40b3SMatthew Dillon
8430ffe40b3SMatthew Dillon while (*cp != '\0' && !isspace(*cp) && *cp != '#')
8440ffe40b3SMatthew Dillon cp++;
8450ffe40b3SMatthew Dillon if ((c = *cp) != '\0') {
8460ffe40b3SMatthew Dillon *cp++ = '\0';
8470ffe40b3SMatthew Dillon if (c != '#')
8480ffe40b3SMatthew Dillon return (skip(cp));
8490ffe40b3SMatthew Dillon }
8500ffe40b3SMatthew Dillon return (NULL);
8510ffe40b3SMatthew Dillon }
8520ffe40b3SMatthew Dillon
8530ffe40b3SMatthew Dillon /*
8540ffe40b3SMatthew Dillon * Read an ascii label in from fd f,
8550ffe40b3SMatthew Dillon * in the same format as that put out by display(),
8560ffe40b3SMatthew Dillon * and fill in lp.
8570ffe40b3SMatthew Dillon */
8580a319615SMatthew Dillon static int
getasciilabel(FILE * f,struct disklabel64 * lp)8590ffe40b3SMatthew Dillon getasciilabel(FILE *f, struct disklabel64 *lp)
8600ffe40b3SMatthew Dillon {
8610ffe40b3SMatthew Dillon char *cp;
8620ffe40b3SMatthew Dillon u_int part;
8630ffe40b3SMatthew Dillon char *tp, line[BUFSIZ];
8640ffe40b3SMatthew Dillon u_long v;
8650ffe40b3SMatthew Dillon uint32_t blksize = 0;
8660ffe40b3SMatthew Dillon uint64_t vv;
8670ffe40b3SMatthew Dillon int lineno = 0, errors = 0;
8680ffe40b3SMatthew Dillon char empty[] = "";
8690ffe40b3SMatthew Dillon
8700ffe40b3SMatthew Dillon bzero(&part_set, sizeof(part_set));
8710ffe40b3SMatthew Dillon bzero(&part_size_type, sizeof(part_size_type));
8720ffe40b3SMatthew Dillon bzero(&part_offset_type, sizeof(part_offset_type));
8730ffe40b3SMatthew Dillon while (fgets(line, sizeof(line) - 1, f)) {
8740ffe40b3SMatthew Dillon lineno++;
875678e8cc6SSascha Wildner if ((cp = strchr(line,'\n')) != NULL)
8760ffe40b3SMatthew Dillon *cp = '\0';
8770ffe40b3SMatthew Dillon cp = skip(line);
8780ffe40b3SMatthew Dillon if (cp == NULL)
8790ffe40b3SMatthew Dillon continue;
8800ffe40b3SMatthew Dillon tp = strchr(cp, ':');
8810ffe40b3SMatthew Dillon if (tp == NULL) {
8820ffe40b3SMatthew Dillon fprintf(stderr, "line %d: syntax error\n", lineno);
8830ffe40b3SMatthew Dillon errors++;
8840ffe40b3SMatthew Dillon continue;
8850ffe40b3SMatthew Dillon }
8860ffe40b3SMatthew Dillon *tp++ = '\0', tp = skip(tp);
8870ffe40b3SMatthew Dillon if (sscanf(cp, "%lu partitions", &v) == 1) {
8880ffe40b3SMatthew Dillon if (v == 0 || v > MAXPARTITIONS64) {
8890ffe40b3SMatthew Dillon fprintf(stderr,
8900ffe40b3SMatthew Dillon "line %d: bad # of partitions\n", lineno);
8910ffe40b3SMatthew Dillon lp->d_npartitions = MAXPARTITIONS64;
8920ffe40b3SMatthew Dillon errors++;
8930ffe40b3SMatthew Dillon } else
8940ffe40b3SMatthew Dillon lp->d_npartitions = v;
8950ffe40b3SMatthew Dillon continue;
8960ffe40b3SMatthew Dillon }
8970ffe40b3SMatthew Dillon if (tp == NULL)
8980ffe40b3SMatthew Dillon tp = empty;
8990ffe40b3SMatthew Dillon
9000ffe40b3SMatthew Dillon if (streq(cp, "diskid")) {
9010ffe40b3SMatthew Dillon uint32_t status = 0;
902529d55c9SMatthew Dillon uuid_from_string(tp, &lp->d_stor_uuid, &status);
9030ffe40b3SMatthew Dillon if (status != uuid_s_ok) {
9040ffe40b3SMatthew Dillon fprintf(stderr,
9050ffe40b3SMatthew Dillon "line %d: %s: illegal UUID\n",
9060ffe40b3SMatthew Dillon lineno, tp);
9070ffe40b3SMatthew Dillon errors++;
9080ffe40b3SMatthew Dillon }
9090ffe40b3SMatthew Dillon continue;
9100ffe40b3SMatthew Dillon }
9110ffe40b3SMatthew Dillon if (streq(cp, "label")) {
9120a319615SMatthew Dillon strlcpy((char *)lp->d_packname, tp, sizeof(lp->d_packname));
9130ffe40b3SMatthew Dillon continue;
9140ffe40b3SMatthew Dillon }
9150ffe40b3SMatthew Dillon
9160ffe40b3SMatthew Dillon if (streq(cp, "alignment")) {
9170ffe40b3SMatthew Dillon v = strtoul(tp, NULL, 0);
9180ffe40b3SMatthew Dillon if (v <= 0 || (v & DEV_BMASK) != 0 || v > 1024*1024) {
9190ffe40b3SMatthew Dillon fprintf(stderr,
9200ffe40b3SMatthew Dillon "line %d: %s: bad alignment\n",
9210ffe40b3SMatthew Dillon lineno, tp);
9220ffe40b3SMatthew Dillon errors++;
9230ffe40b3SMatthew Dillon } else {
9240ffe40b3SMatthew Dillon lp->d_align = v;
9250ffe40b3SMatthew Dillon }
9260ffe40b3SMatthew Dillon continue;
9270ffe40b3SMatthew Dillon }
9280ffe40b3SMatthew Dillon if (streq(cp, "total size")) {
9290ffe40b3SMatthew Dillon vv = strtoull(tp, NULL, 0);
9300ffe40b3SMatthew Dillon if (vv == 0 || vv == (uint64_t)-1) {
9310ffe40b3SMatthew Dillon fprintf(stderr, "line %d: %s: bad %s\n",
9320ffe40b3SMatthew Dillon lineno, tp, cp);
9330ffe40b3SMatthew Dillon errors++;
9340ffe40b3SMatthew Dillon } else {
9350ffe40b3SMatthew Dillon lp->d_total_size = vv;
9360ffe40b3SMatthew Dillon }
9370ffe40b3SMatthew Dillon continue;
9380ffe40b3SMatthew Dillon }
9390ffe40b3SMatthew Dillon if (streq(cp, "boot2 data base")) {
9400ffe40b3SMatthew Dillon vv = strtoull(tp, NULL, 0);
9410ffe40b3SMatthew Dillon if (vv == 0 || vv == (uint64_t)-1) {
9420ffe40b3SMatthew Dillon fprintf(stderr, "line %d: %s: bad %s\n",
9430ffe40b3SMatthew Dillon lineno, tp, cp);
9440ffe40b3SMatthew Dillon errors++;
9450ffe40b3SMatthew Dillon } else {
9460ffe40b3SMatthew Dillon lp->d_bbase = vv;
9470ffe40b3SMatthew Dillon }
9480ffe40b3SMatthew Dillon continue;
9490ffe40b3SMatthew Dillon }
9500ffe40b3SMatthew Dillon if (streq(cp, "partitions data base")) {
9510ffe40b3SMatthew Dillon vv = strtoull(tp, NULL, 0);
9520ffe40b3SMatthew Dillon if (vv == 0 || vv == (uint64_t)-1) {
9530ffe40b3SMatthew Dillon fprintf(stderr, "line %d: %s: bad %s\n",
9540ffe40b3SMatthew Dillon lineno, tp, cp);
9550ffe40b3SMatthew Dillon errors++;
9560ffe40b3SMatthew Dillon } else {
9570ffe40b3SMatthew Dillon lp->d_pbase = vv;
9580ffe40b3SMatthew Dillon }
9590ffe40b3SMatthew Dillon continue;
9600ffe40b3SMatthew Dillon }
9610ffe40b3SMatthew Dillon if (streq(cp, "partitions data stop")) {
9620ffe40b3SMatthew Dillon vv = strtoull(tp, NULL, 0);
9630ffe40b3SMatthew Dillon if (vv == 0 || vv == (uint64_t)-1) {
9640ffe40b3SMatthew Dillon fprintf(stderr, "line %d: %s: bad %s\n",
9650ffe40b3SMatthew Dillon lineno, tp, cp);
9660ffe40b3SMatthew Dillon errors++;
9670ffe40b3SMatthew Dillon } else {
9680ffe40b3SMatthew Dillon lp->d_pstop = vv;
9690ffe40b3SMatthew Dillon }
9700ffe40b3SMatthew Dillon continue;
9710ffe40b3SMatthew Dillon }
9720ffe40b3SMatthew Dillon if (streq(cp, "backup label")) {
9730ffe40b3SMatthew Dillon vv = strtoull(tp, NULL, 0);
9740ffe40b3SMatthew Dillon if (vv == 0 || vv == (uint64_t)-1) {
9750ffe40b3SMatthew Dillon fprintf(stderr, "line %d: %s: bad %s\n",
9760ffe40b3SMatthew Dillon lineno, tp, cp);
9770ffe40b3SMatthew Dillon errors++;
9780ffe40b3SMatthew Dillon } else {
9790ffe40b3SMatthew Dillon lp->d_abase = vv;
9800ffe40b3SMatthew Dillon }
9810ffe40b3SMatthew Dillon continue;
9820ffe40b3SMatthew Dillon }
9830ffe40b3SMatthew Dillon if (streq(cp, "display block size")) {
9840ffe40b3SMatthew Dillon v = strtoul(tp, NULL, 0);
9850ffe40b3SMatthew Dillon if (v <= 0 || (v & DEV_BMASK) != 0 || v > 1024*1024) {
986cd0af6a8SAaron LI fprintf(stderr, "line %d: %s: bad %s\n",
987cd0af6a8SAaron LI lineno, tp, cp);
9880ffe40b3SMatthew Dillon errors++;
9890ffe40b3SMatthew Dillon } else {
9900ffe40b3SMatthew Dillon blksize = v;
9910ffe40b3SMatthew Dillon }
9920ffe40b3SMatthew Dillon continue;
9930ffe40b3SMatthew Dillon }
9940ffe40b3SMatthew Dillon
9950ffe40b3SMatthew Dillon /* the ':' was removed above */
996529d55c9SMatthew Dillon
997529d55c9SMatthew Dillon /*
998529d55c9SMatthew Dillon * Handle main partition data, e.g. a:, b:, etc.
999529d55c9SMatthew Dillon */
1000529d55c9SMatthew Dillon if (*cp < 'a' || *cp > MAX_PART) {
10010ffe40b3SMatthew Dillon fprintf(stderr,
10020ffe40b3SMatthew Dillon "line %d: %s: Unknown disklabel field\n", lineno,
10030ffe40b3SMatthew Dillon cp);
10040ffe40b3SMatthew Dillon errors++;
10050ffe40b3SMatthew Dillon continue;
10060ffe40b3SMatthew Dillon }
10070ffe40b3SMatthew Dillon
10080ffe40b3SMatthew Dillon /* Process a partition specification line. */
10090ffe40b3SMatthew Dillon part = *cp - 'a';
10100ffe40b3SMatthew Dillon if (part >= lp->d_npartitions) {
10110ffe40b3SMatthew Dillon fprintf(stderr,
10120ffe40b3SMatthew Dillon "line %d: partition name out of range a-%c: %s\n",
10130ffe40b3SMatthew Dillon lineno, 'a' + lp->d_npartitions - 1, cp);
10140ffe40b3SMatthew Dillon errors++;
10150ffe40b3SMatthew Dillon continue;
10160ffe40b3SMatthew Dillon }
10170ffe40b3SMatthew Dillon
10180ffe40b3SMatthew Dillon if (blksize == 0) {
10190ffe40b3SMatthew Dillon fprintf(stderr, "block size to use for partition "
10200ffe40b3SMatthew Dillon "display was not specified!\n");
10210ffe40b3SMatthew Dillon errors++;
10220ffe40b3SMatthew Dillon continue;
10230ffe40b3SMatthew Dillon }
10240ffe40b3SMatthew Dillon
1025529d55c9SMatthew Dillon if (strcmp(cp + 1, "-stor_uuid") == 0) {
1026529d55c9SMatthew Dillon if (getasciipartuuid(tp, lp, part, lineno, blksize)) {
10270ffe40b3SMatthew Dillon errors++;
10280ffe40b3SMatthew Dillon break;
10290ffe40b3SMatthew Dillon }
1030529d55c9SMatthew Dillon continue;
1031529d55c9SMatthew Dillon } else if (cp[1] == 0) {
1032529d55c9SMatthew Dillon part_set[part] = 1;
1033529d55c9SMatthew Dillon if (getasciipartspec(tp, lp, part, lineno, blksize)) {
1034529d55c9SMatthew Dillon errors++;
1035529d55c9SMatthew Dillon break;
1036529d55c9SMatthew Dillon }
1037529d55c9SMatthew Dillon continue;
1038529d55c9SMatthew Dillon }
1039529d55c9SMatthew Dillon fprintf(stderr, "line %d: %s: Unknown disklabel field\n",
1040529d55c9SMatthew Dillon lineno, cp);
1041529d55c9SMatthew Dillon errors++;
1042529d55c9SMatthew Dillon continue;
10430ffe40b3SMatthew Dillon }
10440ffe40b3SMatthew Dillon errors += checklabel(lp);
10450ffe40b3SMatthew Dillon return (errors == 0);
10460ffe40b3SMatthew Dillon }
10470ffe40b3SMatthew Dillon
10480a319615SMatthew Dillon static int
parse_field_val(char ** tp,char ** cp,u_int64_t * vv,int lineno)10490ffe40b3SMatthew Dillon parse_field_val(char **tp, char **cp, u_int64_t *vv, int lineno)
10500ffe40b3SMatthew Dillon {
10510ffe40b3SMatthew Dillon char *tmp;
10520ffe40b3SMatthew Dillon
10530ffe40b3SMatthew Dillon if (*tp == NULL || **tp == 0) {
10540ffe40b3SMatthew Dillon fprintf(stderr, "line %d: too few numeric fields\n", lineno);
10550ffe40b3SMatthew Dillon return(-1);
10560ffe40b3SMatthew Dillon }
10570ffe40b3SMatthew Dillon *cp = *tp;
10580ffe40b3SMatthew Dillon *tp = word(*cp);
10590ffe40b3SMatthew Dillon *vv = strtoull(*cp, &tmp, 0);
10600ffe40b3SMatthew Dillon if (*vv == ULLONG_MAX) {
10610ffe40b3SMatthew Dillon fprintf(stderr, "line %d: illegal number\n", lineno);
10620ffe40b3SMatthew Dillon return(-1);
10630ffe40b3SMatthew Dillon }
10640ffe40b3SMatthew Dillon if (tmp)
10650ffe40b3SMatthew Dillon return(*tmp);
10660ffe40b3SMatthew Dillon else
10670ffe40b3SMatthew Dillon return(0);
10680ffe40b3SMatthew Dillon }
10690ffe40b3SMatthew Dillon
10700ffe40b3SMatthew Dillon /*
10710ffe40b3SMatthew Dillon * Read a partition line into partition `part' in the specified disklabel.
10720ffe40b3SMatthew Dillon * Return 0 on success, 1 on failure.
10730ffe40b3SMatthew Dillon */
10740a319615SMatthew Dillon static int
getasciipartspec(char * tp,struct disklabel64 * lp,int part,int lineno,uint32_t blksize)1075529d55c9SMatthew Dillon getasciipartspec(char *tp, struct disklabel64 *lp, int part,
1076529d55c9SMatthew Dillon int lineno, uint32_t blksize)
10770ffe40b3SMatthew Dillon {
10780ffe40b3SMatthew Dillon struct partition64 *pp;
10790ffe40b3SMatthew Dillon char *cp;
10800ffe40b3SMatthew Dillon const char **cpp;
10810ffe40b3SMatthew Dillon int r;
10820ffe40b3SMatthew Dillon u_long v;
10830ffe40b3SMatthew Dillon uint64_t vv;
10840ffe40b3SMatthew Dillon uint64_t mpx;
10850ffe40b3SMatthew Dillon
10860ffe40b3SMatthew Dillon pp = &lp->d_partitions[part];
10870ffe40b3SMatthew Dillon cp = NULL;
10880ffe40b3SMatthew Dillon
10890ffe40b3SMatthew Dillon /*
10900ffe40b3SMatthew Dillon * size
10910ffe40b3SMatthew Dillon */
10920ffe40b3SMatthew Dillon r = parse_field_val(&tp, &cp, &vv, lineno);
10930ffe40b3SMatthew Dillon if (r < 0)
10940ffe40b3SMatthew Dillon return (1);
10950ffe40b3SMatthew Dillon
10960ffe40b3SMatthew Dillon mpx = 1;
10970ffe40b3SMatthew Dillon switch(r) {
10980ffe40b3SMatthew Dillon case 0:
10990ffe40b3SMatthew Dillon mpx = blksize;
11000ffe40b3SMatthew Dillon break;
11010ffe40b3SMatthew Dillon case '%':
11020ffe40b3SMatthew Dillon /* mpx = 1; */
11030ffe40b3SMatthew Dillon break;
11040ffe40b3SMatthew Dillon case '*':
11050ffe40b3SMatthew Dillon mpx = 0;
11060ffe40b3SMatthew Dillon break;
1107f61a91d2SSascha Wildner case 't':
1108f61a91d2SSascha Wildner case 'T':
1109f61a91d2SSascha Wildner mpx *= 1024ULL;
1110f61a91d2SSascha Wildner /* fall through */
11110ffe40b3SMatthew Dillon case 'g':
11120ffe40b3SMatthew Dillon case 'G':
11130ffe40b3SMatthew Dillon mpx *= 1024ULL;
11140ffe40b3SMatthew Dillon /* fall through */
11150ffe40b3SMatthew Dillon case 'm':
11160ffe40b3SMatthew Dillon case 'M':
11170ffe40b3SMatthew Dillon mpx *= 1024ULL;
11180ffe40b3SMatthew Dillon /* fall through */
11190ffe40b3SMatthew Dillon case 'k':
11200ffe40b3SMatthew Dillon case 'K':
11210ffe40b3SMatthew Dillon mpx *= 1024ULL;
11220ffe40b3SMatthew Dillon r = 0; /* eat the suffix */
11230ffe40b3SMatthew Dillon break;
11240ffe40b3SMatthew Dillon default:
1125f61a91d2SSascha Wildner Warning("unknown size specifier '%c' (*/%%/K/M/G/T are valid)",
11260ffe40b3SMatthew Dillon r);
11270ffe40b3SMatthew Dillon return(1);
11280ffe40b3SMatthew Dillon }
11290ffe40b3SMatthew Dillon
11300ffe40b3SMatthew Dillon part_size_type[part] = r;
11310ffe40b3SMatthew Dillon if (vv == 0 && r != '*') {
11320ffe40b3SMatthew Dillon fprintf(stderr,
11330ffe40b3SMatthew Dillon "line %d: %s: bad partition size (0)\n", lineno, cp);
11340ffe40b3SMatthew Dillon return (1);
11350ffe40b3SMatthew Dillon }
11360ffe40b3SMatthew Dillon pp->p_bsize = vv * mpx;
11370ffe40b3SMatthew Dillon
11380ffe40b3SMatthew Dillon /*
11390ffe40b3SMatthew Dillon * offset
11400ffe40b3SMatthew Dillon */
11410ffe40b3SMatthew Dillon r = parse_field_val(&tp, &cp, &vv, lineno);
11420ffe40b3SMatthew Dillon if (r < 0)
11430ffe40b3SMatthew Dillon return (1);
11440ffe40b3SMatthew Dillon part_offset_type[part] = r;
11450ffe40b3SMatthew Dillon switch(r) {
11460ffe40b3SMatthew Dillon case '*':
11470ffe40b3SMatthew Dillon pp->p_boffset = 0;
11480ffe40b3SMatthew Dillon break;
11490ffe40b3SMatthew Dillon case 0:
11500ffe40b3SMatthew Dillon pp->p_boffset = vv * blksize + lp->d_pbase;
11510ffe40b3SMatthew Dillon break;
11520ffe40b3SMatthew Dillon default:
11530ffe40b3SMatthew Dillon fprintf(stderr,
11540ffe40b3SMatthew Dillon "line %d: %s: bad suffix on partition offset (%c)\n",
11550ffe40b3SMatthew Dillon lineno, cp, r);
11560ffe40b3SMatthew Dillon return (1);
11570ffe40b3SMatthew Dillon }
11580ffe40b3SMatthew Dillon
11590ffe40b3SMatthew Dillon /*
11600ffe40b3SMatthew Dillon * fstype
11610ffe40b3SMatthew Dillon */
1162d5c4918aSAntonio Huete Jimenez if (tp == NULL) {
1163d5c4918aSAntonio Huete Jimenez fprintf(stderr,
1164d5c4918aSAntonio Huete Jimenez "line %d: no filesystem type was specified\n", lineno);
1165d5c4918aSAntonio Huete Jimenez return(1);
1166d5c4918aSAntonio Huete Jimenez }
11670ffe40b3SMatthew Dillon cp = tp;
11680ffe40b3SMatthew Dillon tp = word(cp);
1169a8de4644SMatthew Dillon for (cpp = fstypenames; cpp < &fstypenames[FSMAXTYPES]; cpp++) {
1170a8de4644SMatthew Dillon if (*cpp && strcasecmp(*cpp, cp) == 0)
11710ffe40b3SMatthew Dillon break;
1172a8de4644SMatthew Dillon }
11730ffe40b3SMatthew Dillon if (*cpp != NULL) {
11740ffe40b3SMatthew Dillon pp->p_fstype = cpp - fstypenames;
11750ffe40b3SMatthew Dillon } else {
11760ffe40b3SMatthew Dillon if (isdigit(*cp))
11770ffe40b3SMatthew Dillon v = strtoul(cp, NULL, 0);
11780ffe40b3SMatthew Dillon else
11790ffe40b3SMatthew Dillon v = FSMAXTYPES;
11800ffe40b3SMatthew Dillon if (v >= FSMAXTYPES) {
11810ffe40b3SMatthew Dillon fprintf(stderr,
11820ffe40b3SMatthew Dillon "line %d: Warning, unknown filesystem type %s\n",
11830ffe40b3SMatthew Dillon lineno, cp);
11840ffe40b3SMatthew Dillon v = FS_UNUSED;
11850ffe40b3SMatthew Dillon }
11860ffe40b3SMatthew Dillon pp->p_fstype = v;
11870ffe40b3SMatthew Dillon }
11880ffe40b3SMatthew Dillon
11890ffe40b3SMatthew Dillon cp = tp;
11900ffe40b3SMatthew Dillon if (tp) {
11910ffe40b3SMatthew Dillon fprintf(stderr, "line %d: Warning, extra data on line\n",
11920ffe40b3SMatthew Dillon lineno);
11930ffe40b3SMatthew Dillon }
11940ffe40b3SMatthew Dillon return(0);
11950ffe40b3SMatthew Dillon }
11960ffe40b3SMatthew Dillon
11970a319615SMatthew Dillon static int
getasciipartuuid(char * tp,struct disklabel64 * lp,int part,int lineno,uint32_t blksize __unused)1198529d55c9SMatthew Dillon getasciipartuuid(char *tp, struct disklabel64 *lp, int part,
1199529d55c9SMatthew Dillon int lineno, uint32_t blksize __unused)
1200529d55c9SMatthew Dillon {
1201529d55c9SMatthew Dillon struct partition64 *pp;
1202529d55c9SMatthew Dillon uint32_t status;
1203529d55c9SMatthew Dillon char *cp;
1204529d55c9SMatthew Dillon
1205529d55c9SMatthew Dillon pp = &lp->d_partitions[part];
1206529d55c9SMatthew Dillon
1207529d55c9SMatthew Dillon cp = tp;
1208529d55c9SMatthew Dillon tp = word(cp);
1209529d55c9SMatthew Dillon uuid_from_string(cp, &pp->p_stor_uuid, &status);
1210529d55c9SMatthew Dillon if (status != uuid_s_ok) {
1211529d55c9SMatthew Dillon fprintf(stderr, "line %d: Illegal storage uuid specification\n",
1212529d55c9SMatthew Dillon lineno);
1213529d55c9SMatthew Dillon return(1);
1214529d55c9SMatthew Dillon }
1215529d55c9SMatthew Dillon return(0);
1216529d55c9SMatthew Dillon }
1217529d55c9SMatthew Dillon
12180ffe40b3SMatthew Dillon /*
12190ffe40b3SMatthew Dillon * Check disklabel for errors and fill in
12200ffe40b3SMatthew Dillon * derived fields according to supplied values.
12210ffe40b3SMatthew Dillon */
12220a319615SMatthew Dillon static int
checklabel(struct disklabel64 * lp)12230ffe40b3SMatthew Dillon checklabel(struct disklabel64 *lp)
12240ffe40b3SMatthew Dillon {
12250ffe40b3SMatthew Dillon struct partition64 *pp;
12260ffe40b3SMatthew Dillon int errors = 0;
12270ffe40b3SMatthew Dillon char part;
12280ffe40b3SMatthew Dillon u_int64_t total_size;
12290ffe40b3SMatthew Dillon u_int64_t current_offset;
12300ffe40b3SMatthew Dillon u_long total_percent;
12310ffe40b3SMatthew Dillon int seen_default_offset;
12320ffe40b3SMatthew Dillon int hog_part;
12330ffe40b3SMatthew Dillon int i, j;
12340ffe40b3SMatthew Dillon struct partition64 *pp2;
12350ffe40b3SMatthew Dillon u_int64_t off;
12360ffe40b3SMatthew Dillon
12370ffe40b3SMatthew Dillon if (lp->d_align < 512 ||
12380ffe40b3SMatthew Dillon (lp->d_align ^ (lp->d_align - 1)) != lp->d_align * 2 - 1) {
12390ffe40b3SMatthew Dillon Warning("Illegal alignment specified: %u\n", lp->d_align);
12400ffe40b3SMatthew Dillon return (1);
12410ffe40b3SMatthew Dillon }
12420ffe40b3SMatthew Dillon if (lp->d_npartitions > MAXPARTITIONS64) {
12430ffe40b3SMatthew Dillon Warning("number of partitions (%u) > MAXPARTITIONS (%d)",
12440ffe40b3SMatthew Dillon lp->d_npartitions, MAXPARTITIONS64);
12450ffe40b3SMatthew Dillon return (1);
12460ffe40b3SMatthew Dillon }
12470ffe40b3SMatthew Dillon off = offsetof(struct disklabel64, d_partitions[lp->d_npartitions]);
12480ffe40b3SMatthew Dillon off = (off + lp->d_align - 1) & ~(int64_t)(lp->d_align - 1);
12490ffe40b3SMatthew Dillon
12500ffe40b3SMatthew Dillon if (lp->d_bbase < off || lp->d_bbase % lp->d_align) {
12510ffe40b3SMatthew Dillon Warning("illegal boot2 data base ");
12520ffe40b3SMatthew Dillon return (1);
12530ffe40b3SMatthew Dillon }
12545179f0c5SMatthew Dillon
12555179f0c5SMatthew Dillon /*
12565179f0c5SMatthew Dillon * pbase can be unaligned slice-relative but will be
12575179f0c5SMatthew Dillon * aligned physically.
12585179f0c5SMatthew Dillon */
12595179f0c5SMatthew Dillon if (lp->d_pbase < lp->d_bbase) {
12600ffe40b3SMatthew Dillon Warning("illegal partition data base");
12610ffe40b3SMatthew Dillon return (1);
12620ffe40b3SMatthew Dillon }
12635179f0c5SMatthew Dillon if (lp->d_pstop < lp->d_pbase) {
12640ffe40b3SMatthew Dillon Warning("illegal partition data stop");
12650ffe40b3SMatthew Dillon return (1);
12660ffe40b3SMatthew Dillon }
12670ffe40b3SMatthew Dillon if (lp->d_pstop > lp->d_total_size) {
1268a276dc6bSMatthew Dillon printf("%012jx\n%012jx\n",
12691f5e0b99SSascha Wildner (uintmax_t)lp->d_pstop, (uintmax_t)lp->d_total_size);
12700ffe40b3SMatthew Dillon Warning("disklabel control info is beyond the total size");
12710ffe40b3SMatthew Dillon return (1);
12720ffe40b3SMatthew Dillon }
12730ffe40b3SMatthew Dillon if (lp->d_abase &&
12745179f0c5SMatthew Dillon (lp->d_abase < lp->d_pstop ||
12750ffe40b3SMatthew Dillon lp->d_abase > lp->d_total_size - off)) {
12760ffe40b3SMatthew Dillon Warning("illegal backup label location");
12770ffe40b3SMatthew Dillon return (1);
12780ffe40b3SMatthew Dillon }
12790ffe40b3SMatthew Dillon
12800ffe40b3SMatthew Dillon /* first allocate space to the partitions, then offsets */
12810ffe40b3SMatthew Dillon total_size = 0; /* in bytes */
12820ffe40b3SMatthew Dillon total_percent = 0; /* in percent */
12830ffe40b3SMatthew Dillon hog_part = -1;
12840ffe40b3SMatthew Dillon /* find all fixed partitions */
12850ffe40b3SMatthew Dillon for (i = 0; i < (int)lp->d_npartitions; i++) {
12860ffe40b3SMatthew Dillon pp = &lp->d_partitions[i];
12870ffe40b3SMatthew Dillon if (part_set[i]) {
12880ffe40b3SMatthew Dillon if (part_size_type[i] == '*') {
1289b00e432bSMatthew Dillon if (part_offset_type[i] != '*') {
1290b00e432bSMatthew Dillon if (total_size < pp->p_boffset)
1291b00e432bSMatthew Dillon total_size = pp->p_boffset;
1292b00e432bSMatthew Dillon }
1293b00e432bSMatthew Dillon if (hog_part != -1) {
12940ffe40b3SMatthew Dillon Warning("Too many '*' partitions (%c and %c)",
12950ffe40b3SMatthew Dillon hog_part + 'a',i + 'a');
1296b00e432bSMatthew Dillon } else {
12970ffe40b3SMatthew Dillon hog_part = i;
1298b00e432bSMatthew Dillon }
12990ffe40b3SMatthew Dillon } else {
13000ffe40b3SMatthew Dillon off_t size;
13010ffe40b3SMatthew Dillon
13020ffe40b3SMatthew Dillon size = pp->p_bsize;
13030ffe40b3SMatthew Dillon if (part_size_type[i] == '%') {
13040ffe40b3SMatthew Dillon /*
13050ffe40b3SMatthew Dillon * don't count %'s yet
13060ffe40b3SMatthew Dillon */
13070ffe40b3SMatthew Dillon total_percent += size;
13080ffe40b3SMatthew Dillon } else {
13090ffe40b3SMatthew Dillon /*
13100ffe40b3SMatthew Dillon * Value has already been converted
13110ffe40b3SMatthew Dillon * to bytes.
13120ffe40b3SMatthew Dillon */
13130ffe40b3SMatthew Dillon if (size % lp->d_align != 0) {
13140ffe40b3SMatthew Dillon Warning("partition %c's size is not properly aligned",
13150ffe40b3SMatthew Dillon i + 'a');
13160ffe40b3SMatthew Dillon }
13170ffe40b3SMatthew Dillon total_size += size;
13180ffe40b3SMatthew Dillon }
13190ffe40b3SMatthew Dillon }
13200ffe40b3SMatthew Dillon }
13210ffe40b3SMatthew Dillon }
13220ffe40b3SMatthew Dillon /* handle % partitions - note %'s don't need to add up to 100! */
13230ffe40b3SMatthew Dillon if (total_percent != 0) {
13240ffe40b3SMatthew Dillon int64_t free_space;
13250ffe40b3SMatthew Dillon int64_t space_left;
13260ffe40b3SMatthew Dillon
13270ffe40b3SMatthew Dillon free_space = (int64_t)(lp->d_pstop - lp->d_pbase - total_size);
13285179f0c5SMatthew Dillon free_space &= ~(u_int64_t)(lp->d_align - 1);
13295179f0c5SMatthew Dillon
13300ffe40b3SMatthew Dillon space_left = free_space;
13310ffe40b3SMatthew Dillon if (total_percent > 100) {
13320ffe40b3SMatthew Dillon fprintf(stderr,"total percentage %lu is greater than 100\n",
13330ffe40b3SMatthew Dillon total_percent);
13340ffe40b3SMatthew Dillon errors++;
13350ffe40b3SMatthew Dillon }
13360ffe40b3SMatthew Dillon
13370ffe40b3SMatthew Dillon if (free_space > 0) {
13380ffe40b3SMatthew Dillon for (i = 0; i < (int)lp->d_npartitions; i++) {
13390ffe40b3SMatthew Dillon pp = &lp->d_partitions[i];
13400ffe40b3SMatthew Dillon if (part_set[i] && part_size_type[i] == '%') {
13410ffe40b3SMatthew Dillon /* careful of overflows! and integer roundoff */
13420ffe40b3SMatthew Dillon pp->p_bsize = ((double)pp->p_bsize/100) * free_space;
13430ffe40b3SMatthew Dillon pp->p_bsize = (pp->p_bsize + lp->d_align - 1) & ~(u_int64_t)(lp->d_align - 1);
13440ffe40b3SMatthew Dillon if ((int64_t)pp->p_bsize > space_left)
13450ffe40b3SMatthew Dillon pp->p_bsize = (u_int64_t)space_left;
13460ffe40b3SMatthew Dillon total_size += pp->p_bsize;
13470ffe40b3SMatthew Dillon space_left -= pp->p_bsize;
13480ffe40b3SMatthew Dillon }
13490ffe40b3SMatthew Dillon }
13500ffe40b3SMatthew Dillon } else {
1351a276dc6bSMatthew Dillon fprintf(stderr, "%jd bytes available to give to "
1352a276dc6bSMatthew Dillon "'*' and '%%' partitions\n",
1353a276dc6bSMatthew Dillon (intmax_t)free_space);
13540ffe40b3SMatthew Dillon errors++;
13550ffe40b3SMatthew Dillon /* fix? set all % partitions to size 0? */
13560ffe40b3SMatthew Dillon }
13570ffe40b3SMatthew Dillon }
13580ffe40b3SMatthew Dillon /* give anything remaining to the hog partition */
13590ffe40b3SMatthew Dillon if (hog_part != -1) {
13605179f0c5SMatthew Dillon off = lp->d_pstop - lp->d_pbase - total_size;
13615179f0c5SMatthew Dillon off &= ~(u_int64_t)(lp->d_align - 1);
13625179f0c5SMatthew Dillon lp->d_partitions[hog_part].p_bsize = off;
13630ffe40b3SMatthew Dillon total_size = lp->d_pstop - lp->d_pbase;
13640ffe40b3SMatthew Dillon }
13650ffe40b3SMatthew Dillon
13660ffe40b3SMatthew Dillon /* Now set the offsets for each partition */
13670ffe40b3SMatthew Dillon current_offset = lp->d_pbase;
13680ffe40b3SMatthew Dillon seen_default_offset = 0;
13690ffe40b3SMatthew Dillon for (i = 0; i < (int)lp->d_npartitions; i++) {
13700ffe40b3SMatthew Dillon part = 'a' + i;
13710ffe40b3SMatthew Dillon pp = &lp->d_partitions[i];
13720ffe40b3SMatthew Dillon if (pp->p_bsize == 0)
13730ffe40b3SMatthew Dillon continue;
13740ffe40b3SMatthew Dillon if (part_set[i]) {
13750ffe40b3SMatthew Dillon if (part_offset_type[i] == '*') {
13760ffe40b3SMatthew Dillon pp->p_boffset = current_offset;
13770ffe40b3SMatthew Dillon seen_default_offset = 1;
13780ffe40b3SMatthew Dillon } else {
13790ffe40b3SMatthew Dillon /* allow them to be out of order for old-style tables */
13800ffe40b3SMatthew Dillon if (pp->p_boffset < current_offset &&
13810ffe40b3SMatthew Dillon seen_default_offset &&
13820ffe40b3SMatthew Dillon pp->p_fstype != FS_VINUM) {
13830ffe40b3SMatthew Dillon fprintf(stderr,
1384a276dc6bSMatthew Dillon "Offset 0x%012jx for partition %c overlaps previous partition which ends at 0x%012jx\n",
13851f5e0b99SSascha Wildner (uintmax_t)pp->p_boffset,
1386a276dc6bSMatthew Dillon i + 'a',
13871f5e0b99SSascha Wildner (uintmax_t)current_offset);
13880ffe40b3SMatthew Dillon fprintf(stderr,
13890ffe40b3SMatthew Dillon "Labels with any *'s for offset must be in ascending order by sector\n");
13900ffe40b3SMatthew Dillon errors++;
13910ffe40b3SMatthew Dillon } else if (pp->p_boffset != current_offset &&
13920ffe40b3SMatthew Dillon seen_default_offset) {
13930ffe40b3SMatthew Dillon /*
13940ffe40b3SMatthew Dillon * this may give unneeded warnings if
13950ffe40b3SMatthew Dillon * partitions are out-of-order
13960ffe40b3SMatthew Dillon */
13970ffe40b3SMatthew Dillon Warning(
1398a276dc6bSMatthew Dillon "Offset 0x%012jx for partition %c doesn't match expected value 0x%012jx",
13990ffe40b3SMatthew Dillon pp->p_boffset, i + 'a',
1400a276dc6bSMatthew Dillon (intmax_t)current_offset);
14010ffe40b3SMatthew Dillon }
14020ffe40b3SMatthew Dillon }
14030ffe40b3SMatthew Dillon current_offset = pp->p_boffset + pp->p_bsize;
14040ffe40b3SMatthew Dillon }
14050ffe40b3SMatthew Dillon }
14060ffe40b3SMatthew Dillon
14070ffe40b3SMatthew Dillon for (i = 0; i < (int)lp->d_npartitions; i++) {
14080ffe40b3SMatthew Dillon part = 'a' + i;
14090ffe40b3SMatthew Dillon pp = &lp->d_partitions[i];
14100ffe40b3SMatthew Dillon if (pp->p_bsize == 0 && pp->p_boffset != 0)
1411a276dc6bSMatthew Dillon Warning("partition %c: size 0, but offset 0x%012jx",
1412a276dc6bSMatthew Dillon part, (intmax_t)pp->p_boffset);
14130ffe40b3SMatthew Dillon if (pp->p_bsize == 0) {
14140ffe40b3SMatthew Dillon pp->p_boffset = 0;
14150ffe40b3SMatthew Dillon continue;
14160ffe40b3SMatthew Dillon }
1417529d55c9SMatthew Dillon if (uuid_is_nil(&pp->p_stor_uuid, NULL))
1418529d55c9SMatthew Dillon uuid_create(&pp->p_stor_uuid, NULL);
14190ffe40b3SMatthew Dillon
14200ffe40b3SMatthew Dillon if (pp->p_boffset < lp->d_pbase) {
14210ffe40b3SMatthew Dillon fprintf(stderr,
1422a276dc6bSMatthew Dillon "partition %c: offset out of bounds (%jd)\n",
1423a276dc6bSMatthew Dillon part, (intmax_t)(pp->p_boffset - lp->d_pbase));
14240ffe40b3SMatthew Dillon errors++;
14250ffe40b3SMatthew Dillon }
14260ffe40b3SMatthew Dillon if (pp->p_boffset > lp->d_pstop) {
14270ffe40b3SMatthew Dillon fprintf(stderr,
1428a276dc6bSMatthew Dillon "partition %c: offset out of bounds (%jd)\n",
1429a276dc6bSMatthew Dillon part, (intmax_t)(pp->p_boffset - lp->d_pbase));
14300ffe40b3SMatthew Dillon errors++;
14310ffe40b3SMatthew Dillon }
14320ffe40b3SMatthew Dillon if (pp->p_boffset + pp->p_bsize > lp->d_pstop) {
14330ffe40b3SMatthew Dillon fprintf(stderr,
1434a276dc6bSMatthew Dillon "partition %c: size out of bounds (%jd)\n",
1435a276dc6bSMatthew Dillon part, (intmax_t)(pp->p_boffset - lp->d_pbase));
14360ffe40b3SMatthew Dillon errors++;
14370ffe40b3SMatthew Dillon }
14380ffe40b3SMatthew Dillon
14390ffe40b3SMatthew Dillon /* check for overlaps */
14400ffe40b3SMatthew Dillon /* this will check for all possible overlaps once and only once */
14410ffe40b3SMatthew Dillon for (j = 0; j < i; j++) {
14420ffe40b3SMatthew Dillon pp2 = &lp->d_partitions[j];
14430ffe40b3SMatthew Dillon if (pp->p_fstype != FS_VINUM &&
14440ffe40b3SMatthew Dillon pp2->p_fstype != FS_VINUM &&
14450ffe40b3SMatthew Dillon part_set[i] && part_set[j]) {
14460ffe40b3SMatthew Dillon if (pp2->p_boffset < pp->p_boffset + pp->p_bsize &&
14470ffe40b3SMatthew Dillon (pp2->p_boffset + pp2->p_bsize > pp->p_boffset ||
14480ffe40b3SMatthew Dillon pp2->p_boffset >= pp->p_boffset)) {
14490ffe40b3SMatthew Dillon fprintf(stderr,"partitions %c and %c overlap!\n",
14500ffe40b3SMatthew Dillon j + 'a', i + 'a');
14510ffe40b3SMatthew Dillon errors++;
14520ffe40b3SMatthew Dillon }
14530ffe40b3SMatthew Dillon }
14540ffe40b3SMatthew Dillon }
14550ffe40b3SMatthew Dillon }
14560ffe40b3SMatthew Dillon for (; i < (int)lp->d_npartitions; i++) {
14570ffe40b3SMatthew Dillon part = 'a' + i;
14580ffe40b3SMatthew Dillon pp = &lp->d_partitions[i];
14590ffe40b3SMatthew Dillon if (pp->p_bsize || pp->p_boffset)
1460a276dc6bSMatthew Dillon Warning("unused partition %c: size 0x%012jx "
1461a276dc6bSMatthew Dillon "offset 0x%012jx",
1462a276dc6bSMatthew Dillon 'a' + i, (intmax_t)pp->p_bsize,
1463a276dc6bSMatthew Dillon (intmax_t)pp->p_boffset);
14640ffe40b3SMatthew Dillon }
14650ffe40b3SMatthew Dillon return (errors);
14660ffe40b3SMatthew Dillon }
14670ffe40b3SMatthew Dillon
146835a9ab8aSMatthew Dillon static int
expandlabel(int f,struct disklabel64 * lp,int * wbackp)146935a9ab8aSMatthew Dillon expandlabel(int f, struct disklabel64 *lp, int *wbackp)
147035a9ab8aSMatthew Dillon {
147135a9ab8aSMatthew Dillon const uint64_t onemeg = 1024 * 1024;
147235a9ab8aSMatthew Dillon uint64_t pstop;
147335a9ab8aSMatthew Dillon uint64_t abase;
147435a9ab8aSMatthew Dillon uint64_t tsize;
147535a9ab8aSMatthew Dillon uint64_t bsize;
147635a9ab8aSMatthew Dillon struct partinfo info;
147735a9ab8aSMatthew Dillon struct partition64 *part;
147835a9ab8aSMatthew Dillon struct partition64 *best;
147935a9ab8aSMatthew Dillon struct stat st;
148035a9ab8aSMatthew Dillon uint32_t n;
148135a9ab8aSMatthew Dillon
148235a9ab8aSMatthew Dillon if (ioctl(f, DIOCGPART, &info) == 0) {
148335a9ab8aSMatthew Dillon st.st_size = info.media_size;
148435a9ab8aSMatthew Dillon } else if (fstat(f, &st) == 0) {
148535a9ab8aSMatthew Dillon ;
148635a9ab8aSMatthew Dillon } else {
148735a9ab8aSMatthew Dillon fprintf(stderr, "disklabel64: cannot ioctl/stat device\n");
148835a9ab8aSMatthew Dillon return EINVAL;
148935a9ab8aSMatthew Dillon }
149035a9ab8aSMatthew Dillon abase = st.st_size - 4096;
149135a9ab8aSMatthew Dillon pstop = abase & ~(onemeg - 1);
149235a9ab8aSMatthew Dillon tsize = st.st_size;
149335a9ab8aSMatthew Dillon
149435a9ab8aSMatthew Dillon printf("partitions data stop: %ld -> %ld\n", lp->d_pstop, pstop);
149535a9ab8aSMatthew Dillon printf("backup label: %ld -> %ld\n", lp->d_abase, abase);
149635a9ab8aSMatthew Dillon printf("total size: %ld -> %ld\n", lp->d_total_size, tsize);
149735a9ab8aSMatthew Dillon
149835a9ab8aSMatthew Dillon /*
149935a9ab8aSMatthew Dillon * This directive does not shrink disklabels!!!
150035a9ab8aSMatthew Dillon */
150135a9ab8aSMatthew Dillon if (lp->d_pstop > pstop ||
150235a9ab8aSMatthew Dillon lp->d_abase > abase ||
150335a9ab8aSMatthew Dillon lp->d_total_size > tsize) {
150435a9ab8aSMatthew Dillon fprintf(stderr, "disklabel64: cannot expand "
150535a9ab8aSMatthew Dillon "disklabel because it would "
150635a9ab8aSMatthew Dillon "shrink!\n");
150735a9ab8aSMatthew Dillon return 1;
150835a9ab8aSMatthew Dillon }
150935a9ab8aSMatthew Dillon
151035a9ab8aSMatthew Dillon
151135a9ab8aSMatthew Dillon if (lp->d_pstop == pstop &&
151235a9ab8aSMatthew Dillon lp->d_abase == abase &&
151335a9ab8aSMatthew Dillon lp->d_total_size == tsize) {
1514*e04444f9SMatthew Dillon printf("disklabel64: expand: "
151535a9ab8aSMatthew Dillon "no change in disklabel "
151635a9ab8aSMatthew Dillon "size\n");
151735a9ab8aSMatthew Dillon } else {
151835a9ab8aSMatthew Dillon lp->d_pstop = pstop;
151935a9ab8aSMatthew Dillon lp->d_abase = abase;
152035a9ab8aSMatthew Dillon lp->d_total_size = tsize;
152135a9ab8aSMatthew Dillon *wbackp = 1;
152235a9ab8aSMatthew Dillon }
152335a9ab8aSMatthew Dillon
152435a9ab8aSMatthew Dillon /*
152535a9ab8aSMatthew Dillon * Resize the last partition
152635a9ab8aSMatthew Dillon */
152735a9ab8aSMatthew Dillon if (expandopt > 1) {
152835a9ab8aSMatthew Dillon best = NULL;
152935a9ab8aSMatthew Dillon for (n = 0; n < lp->d_npartitions; ++n) {
153035a9ab8aSMatthew Dillon part = &lp->d_partitions[n];
153135a9ab8aSMatthew Dillon if (best == NULL || best->p_boffset < part->p_boffset)
153235a9ab8aSMatthew Dillon best = part;
153335a9ab8aSMatthew Dillon }
153435a9ab8aSMatthew Dillon if (best) {
153535a9ab8aSMatthew Dillon bsize = lp->d_pstop - best->p_boffset;
153635a9ab8aSMatthew Dillon if (best->p_bsize > bsize) {
1537*e04444f9SMatthew Dillon printf("disklabel64: cannot expand "
153835a9ab8aSMatthew Dillon "partition because it would "
153935a9ab8aSMatthew Dillon "shrink!\n");
154035a9ab8aSMatthew Dillon return 1;
154135a9ab8aSMatthew Dillon } else if (best->p_bsize == bsize) {
1542*e04444f9SMatthew Dillon printf("disklabel64: expand: "
154335a9ab8aSMatthew Dillon "no change in partition "
154435a9ab8aSMatthew Dillon "size\n");
154535a9ab8aSMatthew Dillon } else {
1546*e04444f9SMatthew Dillon printf("disklabel64: expand: increase part "
1547*e04444f9SMatthew Dillon "%ld to %ld bytes\n",
1548*e04444f9SMatthew Dillon best->p_bsize,
1549*e04444f9SMatthew Dillon bsize);
155035a9ab8aSMatthew Dillon best->p_bsize = bsize;
155135a9ab8aSMatthew Dillon *wbackp = 1;
155235a9ab8aSMatthew Dillon }
155335a9ab8aSMatthew Dillon }
155435a9ab8aSMatthew Dillon }
155535a9ab8aSMatthew Dillon
155635a9ab8aSMatthew Dillon return 0;
155735a9ab8aSMatthew Dillon }
155835a9ab8aSMatthew Dillon
15590ffe40b3SMatthew Dillon /*
15600ffe40b3SMatthew Dillon * When operating on a "virgin" disk, try getting an initial label
15610ffe40b3SMatthew Dillon * from the associated device driver. This might work for all device
15620ffe40b3SMatthew Dillon * drivers that are able to fetch some initial device parameters
15630ffe40b3SMatthew Dillon * without even having access to a (BSD) disklabel, like SCSI disks,
15640ffe40b3SMatthew Dillon * most IDE drives, or vn devices.
15650ffe40b3SMatthew Dillon *
15660ffe40b3SMatthew Dillon * The device name must be given in its "canonical" form.
15670ffe40b3SMatthew Dillon */
15680ffe40b3SMatthew Dillon static struct disklabel64 dlab;
15690ffe40b3SMatthew Dillon
15700a319615SMatthew Dillon static struct disklabel64 *
getvirginlabel(void)15710ffe40b3SMatthew Dillon getvirginlabel(void)
15720ffe40b3SMatthew Dillon {
15730ffe40b3SMatthew Dillon struct disklabel64 *dl = &dlab;
15740ffe40b3SMatthew Dillon int f;
15750ffe40b3SMatthew Dillon
1576d736a600SMatthew Dillon if ((f = open(dkname, O_RDONLY)) == -1) {
1577d736a600SMatthew Dillon warn("cannot open %s", dkname);
15780ffe40b3SMatthew Dillon return (NULL);
15790ffe40b3SMatthew Dillon }
15800ffe40b3SMatthew Dillon
15810ffe40b3SMatthew Dillon /*
15820a319615SMatthew Dillon * Generate a virgin disklabel via ioctl
15830ffe40b3SMatthew Dillon */
15840ffe40b3SMatthew Dillon if (ioctl(f, DIOCGDVIRGIN64, dl) < 0) {
15850ffe40b3SMatthew Dillon l_perror("ioctl DIOCGDVIRGIN64");
15860ffe40b3SMatthew Dillon close(f);
15870ffe40b3SMatthew Dillon return (NULL);
15880ffe40b3SMatthew Dillon }
15890ffe40b3SMatthew Dillon close(f);
15900ffe40b3SMatthew Dillon return (dl);
15910ffe40b3SMatthew Dillon }
15920ffe40b3SMatthew Dillon
15930ffe40b3SMatthew Dillon /*VARARGS1*/
15940a319615SMatthew Dillon static void
Warning(const char * fmt,...)15950ffe40b3SMatthew Dillon Warning(const char *fmt, ...)
15960ffe40b3SMatthew Dillon {
15970ffe40b3SMatthew Dillon va_list ap;
15980ffe40b3SMatthew Dillon
15990ffe40b3SMatthew Dillon fprintf(stderr, "Warning, ");
16000ffe40b3SMatthew Dillon va_start(ap, fmt);
16010ffe40b3SMatthew Dillon vfprintf(stderr, fmt, ap);
16020ffe40b3SMatthew Dillon fprintf(stderr, "\n");
16030ffe40b3SMatthew Dillon va_end(ap);
16040ffe40b3SMatthew Dillon }
16050ffe40b3SMatthew Dillon
16060a319615SMatthew Dillon static void
usage(void)16070ffe40b3SMatthew Dillon usage(void)
16080ffe40b3SMatthew Dillon {
16090fcbc539SThomas Nikolajsen fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
1610bdddbf50SThomas Nikolajsen "usage: disklabel64 [-r] disk",
16110ffe40b3SMatthew Dillon "\t\t(to read label)",
16120a319615SMatthew Dillon " disklabel64 -w [-r] [-n] disk [type [packid]]",
16130ffe40b3SMatthew Dillon "\t\t(to write label with existing boot program)",
1614bdddbf50SThomas Nikolajsen " disklabel64 -e [-r] [-n] disk",
16150ffe40b3SMatthew Dillon "\t\t(to edit label)",
1616bdddbf50SThomas Nikolajsen " disklabel64 -R [-r] [-n] disk protofile",
16170ffe40b3SMatthew Dillon "\t\t(to restore label with existing boot program)",
16180fcbc539SThomas Nikolajsen " disklabel64 -B [-n] [-b boot1 -s boot2] disk [type]",
16190ffe40b3SMatthew Dillon "\t\t(to install boot program with existing label)",
16200a319615SMatthew Dillon " disklabel64 -w -B [-n] [-b boot1 -s boot2] disk [type [packid]]",
16210ffe40b3SMatthew Dillon "\t\t(to write label and boot program)",
16220fcbc539SThomas Nikolajsen " disklabel64 -R -B [-n] [-b boot1 -s boot2] disk protofile [type]",
16230ffe40b3SMatthew Dillon "\t\t(to restore label and boot program)",
1624bdddbf50SThomas Nikolajsen " disklabel64 [-NW] disk",
16250ffe40b3SMatthew Dillon "\t\t(to write disable/enable label)");
16260ffe40b3SMatthew Dillon exit(1);
16270ffe40b3SMatthew Dillon }
1628