diff options
| author | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
|---|---|---|
| committer | stevel@tonic-gate <none@none> | 2005-06-14 00:00:00 -0700 |
| commit | 7c478bd95313f5f23a4c958a745db2134aa03244 (patch) | |
| tree | c871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/cmd/fmthard | |
| download | illumos-joyent-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz | |
OpenSolaris Launch
Diffstat (limited to 'usr/src/cmd/fmthard')
| -rw-r--r-- | usr/src/cmd/fmthard/Makefile | 56 | ||||
| -rw-r--r-- | usr/src/cmd/fmthard/fmthard.c | 952 |
2 files changed, 1008 insertions, 0 deletions
diff --git a/usr/src/cmd/fmthard/Makefile b/usr/src/cmd/fmthard/Makefile new file mode 100644 index 0000000000..2b077b99f4 --- /dev/null +++ b/usr/src/cmd/fmthard/Makefile @@ -0,0 +1,56 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License, Version 1.0 only +# (the "License"). You may not use this file except in compliance +# with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# +#ident "%Z%%M% %I% %E% SMI" +# +# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# cmd/fmthard/Makefile +# + +PROG= fmthard + +include ../Makefile.cmd + +RELUSRSBIN= ../usr/sbin +ROOTSYMLINK= $(ROOTETC)/$(PROG) +OWNER= root +GROUP= sys +LDLIBS += -ladm -lefi +lint := LINTFLAGS = -u -erroff=E_BAD_FORMAT_ARG_TYPE2 + +.KEEP_STATE: + +all: $(PROG) + +install: all $(ROOTUSRSBINPROG) $(ROOTSYMLINK) + +$(ROOTSYMLINK): + -$(RM) $@; $(SYMLINK) $(RELUSRSBIN)/$(PROG) $@ + +clean: + +lint: lint_PROG + +include ../Makefile.targ + diff --git a/usr/src/cmd/fmthard/fmthard.c b/usr/src/cmd/fmthard/fmthard.c new file mode 100644 index 0000000000..92d44338d8 --- /dev/null +++ b/usr/src/cmd/fmthard/fmthard.c @@ -0,0 +1,952 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ +/* All Rights Reserved */ + + +/* + * + * Portions of this source code were provided by International + * Computers Limited (ICL) under a development agreement with AT&T. + */ + +#pragma ident "%Z%%M% %I% %E% SMI" + +/* + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* + * Sun Microsystems version of fmthard: + * + * Supports the following arguments: + * + * -i Writes VTOC to stdout, rather than disk + * -q Quick check: exit code 0 if VTOC ok + * -d <data> Incremental changes to the VTOC + * -n <vname> Change volume name to <vname> + * -s <file> Read VTOC information from <file>, or stdin ("-") + * -u <state> Reboot after writing VTOC, according to <state>: + * boot: AD_BOOT (standard reboot) + * firm: AD_IBOOT (interactive reboot) + * + * Note that fmthard cannot write a VTOC on an unlabeled disk. + * You must use format or SunInstall for this purpose. + * (NOTE: the above restriction only applies on Sparc systems). + * + * The primary motivation for fmthard is to duplicate the + * partitioning from disk to disk: + * + * prtvtoc /dev/rdsk/c0t0d0s2 | fmthard -s - /dev/rdsk/c0t1d0s2 + */ + +#include <stdio.h> +#include <fcntl.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/param.h> +#include <sys/stat.h> +#include <sys/uadmin.h> +#include <sys/open.h> +#include <sys/vtoc.h> +#include <sys/dkio.h> +#include <sys/isa_defs.h> +#include <sys/efi_partition.h> + +#if defined(_SUNOS_VTOC_16) +#include <sys/dklabel.h> +#endif + +#include <sys/sysmacros.h> + +#ifndef SECSIZE +#define SECSIZE DEV_BSIZE +#endif /* SECSIZE */ + + +/* + * External functions. + */ +extern int read_vtoc(int, struct vtoc *); +extern int write_vtoc(int, struct vtoc *); + +/* + * Externals + */ +extern char *optarg; +extern int optind; +extern int errno; +extern char *sys_errlist[]; + +/* + * Internal functions. + */ +extern int main(int, char **); +static void display(struct dk_geom *, struct vtoc *, char *); +static void display64(struct dk_gpt *, char *); +static void insert(char *, struct vtoc *); +static void insert64(char *, struct dk_gpt *); +static void load(FILE *, struct dk_geom *, struct vtoc *); +static void load64(FILE *, int fd, struct dk_gpt **); +static void usage(void); +static void validate(struct dk_geom *, struct vtoc *); +static void validate64(struct dk_gpt *); +static int vread(int, struct vtoc *, char *); +static void vread64(int, struct dk_gpt **, char *); +static void vwrite(int, struct vtoc *, char *); +static void vwrite64(int, struct dk_gpt *, char *); + +/* + * Static variables. + */ +static char *delta; /* Incremental update */ +static short eflag; /* force write of an EFI label */ +static short iflag; /* Prints VTOC w/o updating */ +static short qflag; /* Check for a formatted disk */ +static short uflag; /* Exit to firmware after writing */ + /* new vtoc and reboot. Used during */ + /* installation of core floppies */ +static diskaddr_t lastlba = 0; /* last LBA on 64-bit VTOC */ + +#if defined(sparc) +static char *uboot = "boot"; + +#elif defined(i386) +/* use installgrub(1M) to install boot blocks */ +static char *uboot = ""; +#else +#error No platform defined. +#endif /* various platform-specific definitions */ + +static char *ufirm = "firm"; +#if defined(_SUNOS_VTOC_16) +static int sectsiz; +static struct vtoc disk_vtoc; +#endif /* defined(_SUNOS_VTOC_16) */ + +int +main(int argc, char **argv) +{ + int fd; + int c; + char *dfile; + char *vname; + struct stat statbuf; +#if defined(_SUNOS_VTOC_8) + struct vtoc disk_vtoc; +#endif /* defined(_SUNOS_VTOC_8) */ + struct dk_gpt *disk_efi; + struct dk_geom disk_geom; + int n; + + + dfile = NULL; + vname = NULL; +#if defined(sparc) + while ((c = getopt(argc, argv, "ed:u:in:qs:")) != EOF) + +#elif defined(i386) + while ((c = getopt(argc, argv, "ed:u:in:qb:p:s:")) != EOF) + +#else +#error No platform defined. +#endif + switch (c) { +#if defined(i386) + case 'p': + case 'b': + (void) fprintf(stderr, + "fmthard: -p and -b no longer supported." + " Use installgrub(1M) to install boot blocks\n"); + break; +#endif /* defined(i386) */ + + case 'd': + delta = optarg; + break; + case 'e': + ++eflag; + break; + case 'i': + ++iflag; + break; + case 'n': + vname = optarg; + break; + case 'q': + ++qflag; + break; + case 's': + dfile = optarg; + break; + case 'u': + if (strcmp(uboot, optarg) == 0) + ++uflag; + else if (strcmp(ufirm, optarg) == 0) + uflag = 2; + + break; + default: + usage(); + } + + + if (argc - optind != 1) + usage(); + + if (stat(argv[optind], (struct stat *)&statbuf) == -1) { + (void) fprintf(stderr, + "fmthard: Cannot stat device %s\n", + argv[optind]); + exit(1); + } + + if ((statbuf.st_mode & S_IFMT) != S_IFCHR) { + (void) fprintf(stderr, + "fmthard: %s must be a raw device.\n", + argv[optind]); + exit(1); + } + + if ((fd = open(argv[optind], O_RDWR|O_NDELAY)) < 0) { + (void) fprintf(stderr, "fmthard: Cannot open device %s - %s\n", + argv[optind], sys_errlist[errno]); + exit(1); + } + + /* + * Get the geometry information for this disk from the driver + */ + if (!eflag && ioctl(fd, DKIOCGGEOM, &disk_geom)) { +#ifdef DEBUG + perror("DKIOCGGEOM failed"); +#endif /* DEBUG */ + if (errno == ENOTSUP) { + /* disk has EFI labels */ + eflag++; + } else { + (void) fprintf(stderr, + "%s: Cannot get disk geometry\n", argv[optind]); + (void) close(fd); + exit(1); + } + } + + /* + * Read the vtoc on the disk + */ + if (!eflag) { + if (vread(fd, &disk_vtoc, argv[optind]) == 1) + eflag++; + } + if (eflag && (dfile == NULL)) { + vread64(fd, &disk_efi, argv[optind]); + } + + /* + * Quick check for valid disk: 0 if ok, 1 if not + */ + if (qflag) { + (void) close(fd); + if (!eflag) { + exit(disk_vtoc.v_sanity == VTOC_SANE ? 0 : 1); + } else { + exit(disk_efi->efi_version <= EFI_VERSION102 ? 0 : 1); + } + } + + /* + * Incremental changes to the VTOC + */ + if (delta) { + if (!eflag) { + insert(delta, &disk_vtoc); + validate(&disk_geom, &disk_vtoc); + vwrite(fd, &disk_vtoc, argv[optind]); + } else { + insert64(delta, disk_efi); + validate64(disk_efi); + vwrite64(fd, disk_efi, argv[optind]); + } + (void) close(fd); + exit(0); + } + + if (!dfile && !vname) + usage(); + + /* + * Read new VTOC from stdin or data file + */ + if (dfile) { + if (strcmp(dfile, "-") == 0) { + if (!eflag) + load(stdin, &disk_geom, &disk_vtoc); + else + load64(stdin, fd, &disk_efi); + } else { + FILE *fp; + if ((fp = fopen(dfile, "r")) == NULL) { + (void) fprintf(stderr, "Cannot open file %s\n", + dfile); + (void) close(fd); + exit(1); + } + if (!eflag) + load(fp, &disk_geom, &disk_vtoc); + else + load64(fp, fd, &disk_efi); + (void) fclose(fp); + } + } + + + /* + * Print the modified VTOC, rather than updating the disk + */ + if (iflag) { + if (!eflag) + display(&disk_geom, &disk_vtoc, argv[optind]); + else + display64(disk_efi, argv[optind]); + (void) close(fd); + exit(0); + } + + if (vname) { + n = MIN(strlen(vname) + 1, LEN_DKL_VVOL); + if (!eflag) { + (void) memcpy(disk_vtoc.v_volume, vname, n); + } else { + for (c = 0; c < disk_efi->efi_nparts; c++) { + if (disk_efi->efi_parts[c].p_tag == + V_RESERVED) { + (void) memcpy(&disk_efi->efi_parts[c].p_name, + vname, n); + } + } + } + + } + /* + * Write the new VTOC on the disk + */ + if (!eflag) { + validate(&disk_geom, &disk_vtoc); + vwrite(fd, &disk_vtoc, argv[optind]); + } else { + validate64(disk_efi); + vwrite64(fd, disk_efi, argv[optind]); + } + + /* + * Shut system down after writing a new vtoc to disk + * This is used during installation of core floppies. + */ + if (uflag == 1) + uadmin(A_REBOOT, AD_BOOT, 0); + else if (uflag == 2) + uadmin(A_REBOOT, AD_IBOOT, 0); + + (void) printf("fmthard: New volume table of contents now in place.\n"); + + return (0); + /*NOTREACHED*/ +} + + + +/* + * display () + * + * display contents of VTOC without writing it to disk + */ +static void +display(struct dk_geom *geom, struct vtoc *vtoc, char *device) +{ + int i; + int c; + + /* + * Print out the VTOC + */ + (void) printf("* %s default partition map\n", device); + if (*vtoc->v_volume) { + (void) printf("* Volume Name: "); + for (i = 0; i < LEN_DKL_VVOL; i++) { + if ((c = vtoc->v_volume[i]) == 0) + break; + (void) printf("%c", c); + } + (void) printf("\n"); + } + (void) printf("*\n"); + (void) printf("* Dimensions:\n"); + (void) printf("* %d bytes/sector\n", SECSIZE); + (void) printf("* %d sectors/track\n", geom->dkg_nsect); + (void) printf("* %d tracks/cylinder\n", geom->dkg_nhead); + (void) printf("* %d cylinders\n", geom->dkg_pcyl); + (void) printf("* %d accessible cylinders\n", geom->dkg_ncyl); + (void) printf("*\n"); + (void) printf("* Flags:\n"); + (void) printf("* 1: unmountable\n"); + (void) printf("* 10: read-only\n"); + (void) printf("*\n"); + (void) printf( +"\n* Partition Tag Flag First Sector Sector Count\n"); + for (i = 0; i < V_NUMPAR; i++) { + if (vtoc->v_part[i].p_size > 0) + (void) printf( +" %d %d 0%x %ld %ld\n", + i, vtoc->v_part[i].p_tag, + vtoc->v_part[i].p_flag, + vtoc->v_part[i].p_start, + vtoc->v_part[i].p_size); + } + exit(0); +} + +/* + * display64 () + * + * display64 contents of EFI partition without writing it to disk + */ +static void +display64(struct dk_gpt *efi, char *device) +{ + int i; + + /* + * Print out the VTOC + */ + (void) printf("* %s default partition map\n", device); + (void) printf("*\n"); + (void) printf("* Dimensions:\n"); + (void) printf("* %d bytes/sector\n", efi->efi_lbasize); + (void) printf("* N/A sectors/track\n"); + (void) printf("* N/A tracks/cylinder\n"); + (void) printf("* N/A cylinders\n"); + (void) printf("* N/A accessible cylinders\n"); + (void) printf("*\n"); + (void) printf("* Flags:\n"); + (void) printf("* 1: unmountable\n"); + (void) printf("* 10: read-only\n"); + (void) printf("*\n"); + (void) printf( +"\n* Partition Tag Flag First Sector Sector Count\n"); + for (i = 0; i < efi->efi_nparts; i++) { + if (efi->efi_parts[i].p_size > 0) + (void) printf( +" %d %d 0%x %8lld %8lld\n", + i, efi->efi_parts[i].p_tag, + efi->efi_parts[i].p_flag, + efi->efi_parts[i].p_start, + efi->efi_parts[i].p_size); + } + exit(0); +} + + +/* + * insert() + * + * Insert a change into the VTOC. + */ +static void +insert(char *data, struct vtoc *vtoc) +{ + int part; + int tag; + uint_t flag; + daddr_t start; + long size; + + if (sscanf(data, "%d:%d:%x:%ld:%ld", + &part, &tag, &flag, &start, &size) != 5) { + (void) fprintf(stderr, "Delta syntax error on \"%s\"\n", data); + exit(1); + } + if (part >= V_NUMPAR) { + (void) fprintf(stderr, + "Error in data \"%s\": No such partition %x\n", + data, part); + exit(1); + } + vtoc->v_part[part].p_tag = (ushort_t)tag; + vtoc->v_part[part].p_flag = (ushort_t)flag; + vtoc->v_part[part].p_start = start; + vtoc->v_part[part].p_size = size; +} + +/* + * insert64() + * + * Insert a change into the VTOC. + */ +static void +insert64(char *data, struct dk_gpt *efi) +{ + int part; + int tag; + uint_t flag; + diskaddr_t start; + diskaddr_t size; + + if (sscanf(data, "%d:%d:%x:%lld:%lld", + &part, &tag, &flag, &start, &size) != 5) { + (void) fprintf(stderr, "Delta syntax error on \"%s\"\n", data); + exit(1); + } + if (part >= efi->efi_nparts) { + (void) fprintf(stderr, + "Error in data \"%s\": No such partition %x\n", + data, part); + exit(1); + } + efi->efi_parts[part].p_tag = (ushort_t)tag; + efi->efi_parts[part].p_flag = (ushort_t)flag; + efi->efi_parts[part].p_start = start; + efi->efi_parts[part].p_size = size; +} + +/* + * load() + * + * Load VTOC information from a datafile. + */ +static void +load(FILE *fp, struct dk_geom *geom, struct vtoc *vtoc) +{ + int part; + int tag; + uint_t flag; + daddr_t start; + long size; + char line[256]; + int i; + long nblks; + long fullsz; + + for (i = 0; i < V_NUMPAR; ++i) { + vtoc->v_part[i].p_tag = 0; + vtoc->v_part[i].p_flag = V_UNMNT; + vtoc->v_part[i].p_start = 0; + vtoc->v_part[i].p_size = 0; + } + /* + * initialize partition 2, by convention it corresponds to whole + * disk. It will be overwritten, if specified in the input datafile + */ + fullsz = geom->dkg_ncyl * geom->dkg_nsect * geom->dkg_nhead; + vtoc->v_part[2].p_tag = V_BACKUP; + vtoc->v_part[2].p_flag = V_UNMNT; + vtoc->v_part[2].p_start = 0; + vtoc->v_part[2].p_size = fullsz; + + nblks = geom->dkg_nsect * geom->dkg_nhead; + + while (fgets(line, sizeof (line) - 1, fp)) { + if (line[0] == '\0' || line[0] == '\n' || line[0] == '*') + continue; + line[strlen(line) - 1] = '\0'; + if (sscanf(line, "%d %d %x %ld %ld", + &part, &tag, &flag, &start, &size) != 5) { + (void) fprintf(stderr, "Syntax error: \"%s\"\n", + line); + exit(1); + } + if (part >= V_NUMPAR) { + (void) fprintf(stderr, + "No such partition %x: \"%s\"\n", + part, line); + exit(1); + } + if (!eflag && ((start % nblks) != 0 || (size % nblks) != 0)) { + (void) fprintf(stderr, +"Partition %d not aligned on cylinder boundary: \"%s\"\n", + part, line); + exit(1); + } + vtoc->v_part[part].p_tag = (ushort_t)tag; + vtoc->v_part[part].p_flag = (ushort_t)flag; + vtoc->v_part[part].p_start = start; + vtoc->v_part[part].p_size = size; + } + for (part = 0; part < V_NUMPAR; part++) { + vtoc->timestamp[part] = (time_t)0; + } +} + +/* + * load64() + * + * Load VTOC information from a datafile. + */ +static void +load64(FILE *fp, int fd, struct dk_gpt **efi) +{ + int part; + int tag; + uint_t flag; + diskaddr_t start; + diskaddr_t size; + int nlines = 0; + char line[256]; + int i; + uint_t max_part = 0; + char **mem = NULL; + + while (fgets(line, sizeof (line) - 1, fp)) { + if (line[0] == '\0' || line[0] == '\n' || line[0] == '*') + continue; + line[strlen(line) - 1] = '\0'; + if (sscanf(line, "%d %d %x %lld %lld", + &part, &tag, &flag, &start, &size) != 5) { + (void) fprintf(stderr, "Syntax error: \"%s\"\n", + line); + exit(1); + } + mem = realloc(mem, sizeof (*mem) * (nlines + 1)); + if (mem == NULL) { + (void) fprintf(stderr, "realloc failed\n"); + exit(1); + } + mem[nlines] = strdup(line); + if (mem[nlines] == NULL) { + (void) fprintf(stderr, "strdup failed\n"); + exit(1); + } + nlines++; + if (part > max_part) + max_part = part; + } + max_part++; + + if ((i = efi_alloc_and_init(fd, max_part, efi)) < 0) { + (void) fprintf(stderr, + "efi_alloc_and_init failed: %d\n", i); + exit(1); + } + for (i = 0; i < (*efi)->efi_nparts; ++i) { + (*efi)->efi_parts[i].p_tag = V_UNASSIGNED; + (*efi)->efi_parts[i].p_flag = V_UNMNT; + (*efi)->efi_parts[i].p_start = 0; + (*efi)->efi_parts[i].p_size = 0; + } + lastlba = (*efi)->efi_last_u_lba; + + for (i = 0; i < nlines; i++) { + if (sscanf(mem[i], "%d %d %x %lld %lld", + &part, &tag, &flag, &start, &size) != 5) { + (void) fprintf(stderr, "Syntax error: \"%s\"\n", + line); + exit(1); + } + free(mem[i]); + if (part >= (*efi)->efi_nparts) { + (void) fprintf(stderr, + "No such partition %x: \"%s\"\n", + part, line); + exit(1); + } + (*efi)->efi_parts[part].p_tag = (ushort_t)tag; + (*efi)->efi_parts[part].p_flag = (ushort_t)flag; + (*efi)->efi_parts[part].p_start = start; + (*efi)->efi_parts[part].p_size = size; + } + (*efi)->efi_nparts = max_part; + free(mem); +} + + +static void +usage() +{ + (void) fprintf(stderr, +#if defined(sparc) +"Usage: fmthard [ -i ] [ -n volumename ] [ -s datafile ] [ -d arguments] \ +raw-device\n"); + +#elif defined(i386) +"Usage: fmthard [ -i ] [ -S ] [-I geom_file] \ +-n volumename | -s datafile [ -d arguments] raw-device\n"); + +#else +#error No platform defined. +#endif + exit(2); +} + +/* + * validate() + * + * Validate the new VTOC. + */ +static void +validate(struct dk_geom *geom, struct vtoc *vtoc) +{ + int i; + int j; + long fullsz; + long endsect; + daddr_t istart; + daddr_t jstart; + long isize; + long jsize; + long nblks; + + nblks = geom->dkg_nsect * geom->dkg_nhead; + + fullsz = geom->dkg_ncyl * geom->dkg_nsect * geom->dkg_nhead; + +#if defined(_SUNOS_VTOC_16) + /* make the vtoc look sane - ha ha */ + vtoc->v_version = V_VERSION; + vtoc->v_sanity = VTOC_SANE; + vtoc->v_nparts = V_NUMPAR; + if (sectsiz == 0) + sectsiz = SECSIZE; + if (vtoc->v_sectorsz == 0) + vtoc->v_sectorsz = sectsiz; +#endif /* defined(_SUNOS_VTOC_16) */ + + for (i = 0; i < V_NUMPAR; i++) { + if (vtoc->v_part[i].p_tag == V_BACKUP) { + if (vtoc->v_part[i].p_size != fullsz) { + (void) fprintf(stderr, "\ +fmthard: Partition %d specifies the full disk and is not equal\n\ +full size of disk. The full disk capacity is %lu sectors.\n", i, fullsz); +#if defined(sparc) + exit(1); +#endif + } + } + if (vtoc->v_part[i].p_size == 0) + continue; /* Undefined partition */ + if ((vtoc->v_part[i].p_start % nblks) || + (vtoc->v_part[i].p_size % nblks)) { + (void) fprintf(stderr, "\ +fmthard: Partition %d not aligned on cylinder boundary \n", i); + exit(1); + } + if (vtoc->v_part[i].p_start > fullsz || + vtoc->v_part[i].p_start + + vtoc->v_part[i].p_size > fullsz) { + (void) fprintf(stderr, "\ +fmthard: Partition %d specified as %lu sectors starting at %lu\n\ +\tdoes not fit. The full disk contains %lu sectors.\n", + i, vtoc->v_part[i].p_size, + vtoc->v_part[i].p_start, fullsz); +#if defined(sparc) + exit(1); +#endif + } + + if (vtoc->v_part[i].p_tag != V_BACKUP && + vtoc->v_part[i].p_size != fullsz) { + for (j = 0; j < V_NUMPAR; j++) { + if (vtoc->v_part[j].p_tag == V_BACKUP) + continue; + if (vtoc->v_part[j].p_size == fullsz) + continue; + isize = vtoc->v_part[i].p_size; + jsize = vtoc->v_part[j].p_size; + istart = vtoc->v_part[i].p_start; + jstart = vtoc->v_part[j].p_start; + if ((i != j) && + (isize != 0) && (jsize != 0)) { + endsect = jstart + jsize -1; + if ((jstart <= istart) && + (istart <= endsect)) { + (void) fprintf(stderr, "\ +fmthard: Partition %d overlaps partition %d. Overlap is allowed\n\ +\tonly on partition on the full disk partition).\n", + i, j); +#if defined(sparc) + exit(1); +#endif + } + } + } + } + } +} + +/* + * validate64() + * + * Validate the new VTOC. + */ +static void +validate64(struct dk_gpt *efi) +{ + int i; + int j; + int resv_part = 0; + diskaddr_t endsect; + diskaddr_t fullsz; + diskaddr_t istart; + diskaddr_t jstart; + diskaddr_t isize; + diskaddr_t jsize; + + fullsz = lastlba + 1; + + for (i = 0; i < efi->efi_nparts; i++) { + if (efi->efi_parts[i].p_size == 0) + continue; /* Undefined partition */ + if (efi->efi_parts[i].p_tag == V_RESERVED) + resv_part++; + if (efi->efi_parts[i].p_start > fullsz || + efi->efi_parts[i].p_start + + efi->efi_parts[i].p_size > fullsz) { + (void) fprintf(stderr, "\ +fmthard: Partition %d specified as %lld sectors starting at %lld\n\ +\tdoes not fit. The full disk contains %lld sectors.\n", + i, efi->efi_parts[i].p_size, + efi->efi_parts[i].p_start, fullsz); + exit(1); + } + + if (efi->efi_parts[i].p_tag != V_BACKUP && + efi->efi_parts[i].p_size != fullsz) { + for (j = 0; j < V_NUMPAR; j++) { + if (efi->efi_parts[j].p_size == fullsz) + continue; + isize = efi->efi_parts[i].p_size; + jsize = efi->efi_parts[j].p_size; + istart = efi->efi_parts[i].p_start; + jstart = efi->efi_parts[j].p_start; + if ((i != j) && + (isize != 0) && (jsize != 0)) { + endsect = jstart + jsize - 1; + if ((jstart <= istart) && + (istart <= endsect)) { + (void) fprintf(stderr, "\ +fmthard: Partition %d overlaps partition %d. Overlap is allowed\n\ +\tonly on partition on the full disk partition).\n", + i, j); +#if defined(sparc) + exit(1); +#endif + } + } + } + } + } + if (resv_part != 1) { + (void) fprintf(stderr, + "expected one reserved partition, but found %d\n", + resv_part); + exit(1); + } +} + + +/* + * Read the VTOC + */ +int +vread(int fd, struct vtoc *vtoc, char *devname) +{ + int i; + + if ((i = read_vtoc(fd, vtoc)) < 0) { + if (i == VT_ENOTSUP) { + return (1); + } + if (i == VT_EINVAL) { + (void) fprintf(stderr, "%s: Invalid VTOC\n", + devname); + } else { + (void) fprintf(stderr, "%s: Cannot read VTOC\n", + devname); + } + exit(1); + } + return (0); +} + +void +vread64(int fd, struct dk_gpt **efi_hdr, char *devname) +{ + int i; + + if ((i = efi_alloc_and_read(fd, efi_hdr)) < 0) { + if (i == VT_EINVAL) + (void) fprintf(stderr, + "%s: this disk must be labeled first\n", + devname); + else + (void) fprintf(stderr, + "%s: read_efi failed %d\n", + devname, i); + exit(1); + } + lastlba = (*efi_hdr)->efi_last_u_lba; +} + +/* + * Write the VTOC + */ +void +vwrite(int fd, struct vtoc *vtoc, char *devname) +{ + int i; + + if ((i = write_vtoc(fd, vtoc)) != 0) { + if (i == VT_EINVAL) { + (void) fprintf(stderr, + "%s: invalid entry exists in vtoc\n", + devname); + } else { + (void) fprintf(stderr, "%s: Cannot write VTOC\n", + devname); + } + exit(1); + } +} + +/* + * Write the VTOC + */ +void +vwrite64(int fd, struct dk_gpt *efi, char *devname) +{ + int i; + + if ((i = efi_write(fd, efi)) != 0) { + if (i == VT_EINVAL) { + (void) fprintf(stderr, + "%s: invalid entry exists in vtoc\n", + devname); + } else { + (void) fprintf(stderr, "%s: Cannot write EFI\n", + devname); + } + exit(1); + } +} |
