fmthard.c revision 2f7fafa7935da94ab2ddd926b525aabc1dd48264
/*
* 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 *);
/*
* 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;
disk_efi = NULL;
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], strerror(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) || qflag)) {
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);
}
}