summaryrefslogtreecommitdiff
path: root/sbin/disklabel
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1995-10-18 08:53:40 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1995-10-18 08:53:40 +0000
commitd6583bb2a13f329cf0332ef2570eb8bb8fc0e39c (patch)
treeece253b876159b39c620e62b6c9b1174642e070e /sbin/disklabel
initial import of NetBSD tree
Diffstat (limited to 'sbin/disklabel')
-rw-r--r--sbin/disklabel/Makefile24
-rw-r--r--sbin/disklabel/disklabel.5381
-rw-r--r--sbin/disklabel/disklabel.8345
-rw-r--r--sbin/disklabel/disklabel.c1407
-rw-r--r--sbin/disklabel/dkcksum.c59
-rw-r--r--sbin/disklabel/pathnames.h42
6 files changed, 2258 insertions, 0 deletions
diff --git a/sbin/disklabel/Makefile b/sbin/disklabel/Makefile
new file mode 100644
index 00000000000..b663319f6dc
--- /dev/null
+++ b/sbin/disklabel/Makefile
@@ -0,0 +1,24 @@
+# $NetBSD: Makefile,v 1.17 1995/04/23 19:27:59 ragge Exp $
+# @(#)Makefile 8.2 (Berkeley) 3/17/94
+
+PROG= disklabel
+SRCS= disklabel.c dkcksum.c
+MAN= disklabel.5 disklabel.8
+
+.if ${MACHINE} == "amiga"
+CFLAGS+= -D${MACHINE}
+.endif
+
+.if (${MACHINE} == "i386") || (${MACHINE} == "alpha")
+CFLAGS+= -DNUMBOOT=2
+.endif
+
+.if (${MACHINE} == "hp300") || (${MACHINE} == "vax")
+CFLAGS+= -DNUMBOOT=1
+.endif
+
+.if ${MACHINE} == "i386"
+CFLAGS+= -DRAWPARTITION=\'d\'
+.endif
+
+.include <bsd.prog.mk>
diff --git a/sbin/disklabel/disklabel.5 b/sbin/disklabel/disklabel.5
new file mode 100644
index 00000000000..1dcc22cd1c9
--- /dev/null
+++ b/sbin/disklabel/disklabel.5
@@ -0,0 +1,381 @@
+.\" $NetBSD: disklabel.5,v 1.3 1995/03/18 14:54:36 cgd Exp $
+.\"
+.\" Copyright (c) 1987, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Symmetric Computer Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)disklabel.5.5 8.1 (Berkeley) 6/5/93
+.\"
+.Dd June 5, 1993
+.Dt DISKLABEL 5
+.Os
+.Sh NAME
+.Nm disklabel
+.Nd disk pack label
+.Sh SYNOPSIS
+.Fd #include <sys/disklabel.h>
+.Sh DESCRIPTION
+Each disk or disk pack on a system may contain a disk label
+which provides detailed information
+about the geometry of the disk and the partitions into which the disk
+is divided.
+It should be initialized when the disk is formatted,
+and may be changed later with the
+.Xr disklabel 8
+program.
+This information is used by the system disk driver and by the bootstrap
+program to determine how to program the drive
+and where to find the filesystems on the disk partitions.
+Additional information is used by the filesystem in order
+to use the disk most efficiently and to locate important filesystem information.
+The description of each partition contains an identifier for the partition
+type (standard filesystem, swap area, etc.).
+The filesystem updates the in-core copy of the label if it contains
+incomplete information about the filesystem.
+.Pp
+The label is located in sector number
+.Dv LABELSECTOR
+of the drive, usually sector 0 where it may be found
+without any information about the disk geometry.
+It is at an offset
+.Dv LABELOFFSET
+from the beginning of the sector, to allow room for the initial bootstrap.
+The disk sector containing the label is normally made read-only
+so that it is not accidentally overwritten by pack-to-pack copies
+or swap operations;
+the
+.Dv DIOCWLABEL
+.Xr ioctl 2 ,
+which is done as needed by the
+.Xr disklabel
+program.
+.Pp
+A copy of the in-core label for a disk can be obtained with the
+.Dv DIOCGDINFO
+.Xr ioctl ;
+this works with a file descriptor for a block or character (``raw'') device
+for any partition of the disk.
+The in-core copy of the label is set by the
+.Dv DIOCSDINFO
+.Xr ioctl .
+The offset of a partition cannot generally be changed while it is open,
+nor can it be made smaller while it is open.
+One exception is that any change is allowed if no label was found
+on the disk, and the driver was able to construct only a skeletal label
+without partition information.
+Finally, the
+.Dv DIOCWDINFO
+.Xr ioctl
+operation sets the in-core label and then updates the on-disk label;
+there must be an existing label on the disk for this operation to succeed.
+Thus, the initial label for a disk or disk pack must be installed
+by writing to the raw disk.
+All of these operations are normally done using
+.Xr disklabel .
+.Pp
+The format of the disk label, as specified in
+.Aw Pa sys/disklabel.h ,
+is
+.Bd -literal
+/*
+* Disk description table, see disktab(5)
+*/
+#define DISKTAB "/etc/disktab"
+
+/*
+* Each disk has a label which includes information about the hardware
+* disk geometry, filesystem partitions, and drive specific information.
+* The label is in block 0 or 1, possibly offset from the beginning
+* to leave room for a bootstrap, etc.
+*/
+
+#ifndef LABELSECTOR
+#define LABELSECTOR 0 /* sector containing label */
+#endif
+
+#ifndef LABELOFFSET
+#define LABELOFFSET 64 /* offset of label in sector */
+#endif
+
+#define DISKMAGIC ((u_long) 0x82564557) /* The disk magic number */
+#ifndef MAXPARTITIONS
+#define MAXPARTITIONS 8
+#endif
+
+#ifndef LOCORE
+struct disklabel {
+ u_long d_magic; /* the magic number */
+ short d_type; /* drive type */
+ short d_subtype; /* controller/d_type specific */
+ char d_typename[16]; /* type name, e.g. "eagle" */
+ /*
+ * d_packname contains the pack identifier and is returned when
+ * the disklabel is read off the disk or in-core copy.
+ * d_boot0 and d_boot1 are the (optional) names of the
+ * primary (block 0) and secondary (block 1-15) bootstraps
+ * as found in /usr/mdec. These are returned when using
+ * getdiskbyname(3)
+ to retrieve the values from /etc/disktab.
+ */
+ union {
+ char un_d_packname[16]; /* pack identifier */
+ struct {
+ char *un_d_boot0; /* primary bootstrap name */
+ char *un_d_boot1; /* secondary bootstrap name */
+ } un_b;
+ } d_un;
+#define d_packname d_un.un_d_packname
+#define d_boot0 d_un.un_b.un_d_boot0
+#define d_boot1 d_un.un_b.un_d_boot1
+
+ /* disk geometry: */
+ u_long d_secsize; /* # of bytes per sector */
+ u_long d_nsectors; /* # of data sectors per track */
+ u_long d_ntracks; /* # of tracks per cylinder */
+ u_long d_ncylinders; /* # of data cylinders per unit */
+ u_long d_secpercyl; /* # of data sectors per cylinder */
+ u_long d_secperunit; /* # of data sectors per unit */
+ /*
+ * Spares (bad sector replacements) below
+ * are not counted in d_nsectors or d_secpercyl.
+ * Spare sectors are assumed to be physical sectors
+ * which occupy space at the end of each track and/or cylinder.
+ */
+ u_short d_sparespertrack; /* # of spare sectors per track */
+ u_short d_sparespercyl; /* # of spare sectors per cylinder */
+ /*
+ * Alternate cylinders include maintenance, replacement,
+ * configuration description areas, etc.
+ */
+ u_long d_acylinders; /* # of alt. cylinders per unit */
+
+ /* hardware characteristics: */
+ /*
+ * d_interleave, d_trackskew and d_cylskew describe perturbations
+ * in the media format used to compensate for a slow controller.
+ * Interleave is physical sector interleave, set up by the formatter
+ * or controller when formatting. When interleaving is in use,
+ * logically adjacent sectors are not physically contiguous,
+ * but instead are separated by some number of sectors.
+ * It is specified as the ratio of physical sectors traversed
+ * per logical sector. Thus an interleave of 1:1 implies contiguous
+ * layout, while 2:1 implies that logical sector 0 is separated
+ * by one sector from logical sector 1.
+ * d_trackskew is the offset of sector 0 on track N
+ * relative to sector 0 on track N-1 on the same cylinder.
+ * Finally, d_cylskew is the offset of sector 0 on cylinder N
+ * relative to sector 0 on cylinder N-1.
+ */
+ u_short d_rpm; /* rotational speed */
+ u_short d_interleave; /* hardware sector interleave */
+ u_short d_trackskew; /* sector 0 skew, per track */
+ u_short d_cylskew; /* sector 0 skew, per cylinder */
+ u_long d_headswitch; /* head switch time, usec */
+ u_long d_trkseek; /* track-to-track seek, usec */
+ u_long d_flags; /* generic flags */
+#define NDDATA 5
+ u_long d_drivedata[NDDATA]; /* drive-type specific information */
+#define NSPARE 5
+ u_long d_spare[NSPARE]; /* reserved for future use */
+ u_long d_magic2; /* the magic number (again) */
+ u_short d_checksum; /* xor of data incl. partitions */
+
+ /* filesystem and partition information: */
+ u_short d_npartitions; /* number of partitions in following */
+ u_long d_bbsize; /* size of boot area at sn0, bytes */
+ u_long d_sbsize; /* max size of fs superblock, bytes */
+ struct partition { /* the partition table */
+ u_long p_size; /* number of sectors in partition */
+ u_long p_offset; /* starting sector */
+ u_long p_fsize; /* filesystem basic fragment size */
+ u_char p_fstype; /* filesystem type, see below */
+ u_char p_frag; /* filesystem fragments per block */
+ union {
+ u_short cpg; /* UFS: FS cylinders per group */
+ u_short sgs; /* LFS: FS segment shift */
+ } __partition_u1;
+#define p_cpg __partition_u1.cpg
+#define p_sgs __partition_u1.sgs
+ u_short p_cpg; /* filesystem cylinders per group */
+ } d_partitions[MAXPARTITIONS]; /* actually may be more */
+};
+
+/* d_type values: */
+#define DTYPE_SMD 1 /* SMD, XSMD; VAX hp/up */
+#define DTYPE_MSCP 2 /* MSCP */
+#define DTYPE_DEC 3 /* other DEC (rk, rl) */
+#define DTYPE_SCSI 4 /* SCSI */
+#define DTYPE_ESDI 5 /* ESDI interface */
+#define DTYPE_ST506 6 /* ST506 etc. */
+#define DTYPE_HPIB 7 /* CS/80 on HP-IB */
+#define DTYPE_HPFL 8 /* HP Fiber-link */
+#define DTYPE_FLOPPY 10 /* floppy */
+
+#ifdef DKTYPENAMES
+static char *dktypenames[] = {
+ "unknown",
+ "SMD",
+ "MSCP",
+ "old DEC",
+ "SCSI",
+ "ESDI",
+ "ST506",
+ "HP-IB",
+ "HP-FL",
+ "type 9",
+ "floppy",
+ 0
+};
+#define DKMAXTYPES (sizeof(dktypenames) / sizeof(dktypenames[0]) - 1)
+#endif
+
+/*
+* Filesystem type and version.
+* Used to interpret other filesystem-specific
+* per-partition information.
+*/
+#define FS_UNUSED 0 /* unused */
+#define FS_SWAP 1 /* swap */
+#define FS_V6 2 /* Sixth Edition */
+#define FS_V7 3 /* Seventh Edition */
+#define FS_SYSV 4 /* System V */
+#define FS_V71K 5 /* V7 with 1K blocks (4.1, 2.9) */
+#define FS_V8 6 /* Eighth Edition, 4K blocks */
+#define FS_BSDFFS 7 /* 4.2BSD fast file system */
+#define FS_MSDOS 8 /* MSDOS file system */
+#define FS_BSDLFS 9 /* 4.4BSD log-structured file system */
+#define FS_OTHER 10 /* in use, but unknown/unsupported */
+#define FS_HPFS 11 /* OS/2 high-performance file system */
+#define FS_ISO9660 12 /* ISO 9660, normally CD-ROM */
+#define FS_BOOT 13 /* partition contains bootstrap */
+
+#ifdef DKTYPENAMES
+static char *fstypenames[] = {
+ "unused",
+ "swap",
+ "Version 6",
+ "Version 7",
+ "System V",
+ "4.1BSD",
+ "Eighth Edition",
+ "4.2BSD",
+ "MSDOS",
+ "4.4LFS",
+ "unknown",
+ "HPFS",
+ "ISO9660",
+ "boot",
+ 0
+};
+#define FSMAXTYPES (sizeof(fstypenames) / sizeof(fstypenames[0]) - 1)
+#endif
+
+/*
+* flags shared by various drives:
+*/
+#define D_REMOVABLE 0x01 /* removable media */
+#define D_ECC 0x02 /* supports ECC */
+#define D_BADSECT 0x04 /* supports bad sector forw. */
+#define D_RAMDISK 0x08 /* disk emulator */
+#define D_CHAIN 0x10 /* can do back-back transfers */
+
+/*
+* Drive data for SMD.
+*/
+
+#define d_smdflags d_drivedata[0]
+#define D_SSE 0x1 /* supports skip sectoring */
+#define d_mindist d_drivedata[1]
+#define d_maxdist d_drivedata[2]
+#define d_sdist d_drivedata[3]
+
+/*
+* Drive data for ST506.
+*/
+#define d_precompcyl d_drivedata[0]
+#define d_gap3 d_drivedata[1] /* used only when formatting */
+
+/*
+ * Drive data for SCSI.
+ */
+#define d_blind d_drivedata[0]
+
+#ifndef LOCORE
+/*
+* Structure used to perform a format
+* or other raw operation, returning data
+* and/or register values.
+* Register identification and format
+* are device- and driver-dependent.
+*/
+struct format_op {
+ char *df_buf;
+ int df_count; /* value-result */
+ daddr_t df_startblk;
+ int df_reg[8]; /* result */
+};
+
+/*
+* Structure used internally to retrieve
+* information about a partition on a disk.
+*/
+struct partinfo {
+ struct disklabel *disklab;
+ struct partition *part;
+};
+
+/*
+* Disk-specific ioctls.
+*/
+ /* get and set disklabel; DIOCGPART used internally */
+#define DIOCGDINFO _IOR('d', 101, struct disklabel) /* get */
+#define DIOCSDINFO _IOW('d', 102, struct disklabel) /* set */
+#define DIOCWDINFO _IOW('d', 103, struct disklabel) /* set, update disk */
+#define DIOCGPART _IOW('d', 104, struct partinfo) /* get partition */
+
+/* do format operation, read or write */
+#define DIOCRFORMAT _IOWR('d', 105, struct format_op)
+#define DIOCWFORMAT _IOWR('d', 106, struct format_op)
+
+#define DIOCSSTEP _IOW('d', 107, int) /* set step rate */
+#define DIOCSRETRIES _IOW('d', 108, int) /* set # of retries */
+#define DIOCWLABEL _IOW('d', 109, int) /* write en/disable label */
+
+#define DIOCSBAD _IOW('d', 110, struct dkbad) /* set kernel dkbad */
+
+#endif LOCORE
+.Ed
+.Sh SEE ALSO
+.Xr disktab 5 ,
+.Xr disklabel 8
+.Sh HISTORY
diff --git a/sbin/disklabel/disklabel.8 b/sbin/disklabel/disklabel.8
new file mode 100644
index 00000000000..3a57dd377a5
--- /dev/null
+++ b/sbin/disklabel/disklabel.8
@@ -0,0 +1,345 @@
+.\" $NetBSD: disklabel.8,v 1.9 1995/03/18 14:54:38 cgd Exp $
+.\"
+.\" Copyright (c) 1987, 1988, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Symmetric Computer Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)disklabel.8 8.2 (Berkeley) 4/19/94
+.\"
+.Dd "April 19, 1994"
+.Dt DISKLABEL 8
+.Os BSD 4.2
+.Sh NAME
+.Nm disklabel
+.Nd read and write disk pack label
+.Sh SYNOPSIS
+.Nm disklabel
+.Op Fl r
+.Ar disk
+.Nm disklabel
+.Fl w
+.Op Fl r
+.Ar disk Ar disktype
+.Oo Ar packid Oc
+.Nm disklabel
+.Fl e
+.Op Fl r
+.Ar disk
+.Nm disklabel
+.Fl R
+.Op Fl r
+.Ar disk Ar protofile
+.Nm disklabel
+.Op Fl NW
+.Ar disk
+.sp
+.Nm disklabel
+.Fl B
+.Oo
+.Fl b Ar boot1
+.Op Fl s Ar boot2
+.Oc
+.Ar disk
+.Oo Ar disktype Oc
+.Nm disklabel
+.Fl w
+.Fl B
+.Oo
+.Fl b Ar boot1
+.Op Fl s Ar boot2
+.Oc
+.Ar disk Ar disktype
+.Oo Ar packid Oc
+.Nm disklabel
+.Fl R
+.Fl B
+.Oo
+.Fl b Ar boot1
+.Op Fl s Ar boot2
+.Oc
+.Ar disk Ar protofile
+.Oo Ar disktype Oc
+.Sh DESCRIPTION
+.Nm Disklabel
+can be used to install, examine or modify the label on a disk drive or pack.
+When writing the label, it can be used
+to change the drive identification,
+the disk partitions on the drive,
+or to replace a damaged label.
+On some systems,
+.Nm disklabel
+can be used to install bootstrap code as well.
+There are several forms of the command that read (display), install or edit
+the label on a disk.
+Each form has an additional option,
+.Fl r ,
+which causes the label to be read from or written to the disk directly,
+rather than going through the system's in-core copy of the label.
+This option may allow a label to be installed on a disk
+without kernel support for a label, such as when labels are first installed
+on a system; it must be used when first installing a label on a disk.
+The specific effect of
+.Fl r
+is described under each command.
+The read and install forms also support the
+.Fl B
+option to install bootstrap code.
+These variants are described later.
+.Pp
+The first form of the command (read) is used to examine the label on the named
+disk drive (e.g. sd0 or /dev/rsd0c).
+It will display all of the parameters associated with the drive
+and its partition layout.
+Unless the
+.Fl r
+flag is given,
+the kernel's in-core copy of the label is displayed;
+if the disk has no label, or the partition types on the disk are incorrect,
+the kernel may have constructed or modified the label.
+If the
+.Fl r
+flag is given, the label from the raw disk will be displayed rather
+than the in-core label.
+.Pp
+The second form of the command, with the
+.Fl w
+flag, is used to write a standard label on the designated drive.
+The required arguments to
+.Nm disklabel
+are the drive to be labelled (e.g. sd0), and
+the drive type as described in the
+.Xr disktab 5
+file.
+The drive parameters and partitions are taken from that file.
+If different disks of the same physical type are to have different
+partitions, it will be necessary to have separate disktab entries
+describing each, or to edit the label after installation as described below.
+The optional argument is a pack identification string,
+up to 16 characters long.
+The pack id must be quoted if it contains blanks.
+If the
+.Fl r
+flag is given, the disk sectors containing the label and bootstrap
+will be written directly.
+A side-effect of this is that any existing bootstrap code will be overwritten
+and the disk rendered unbootable.
+If
+.Fl r
+is not specified,
+the existing label will be updated via the in-core copy and any bootstrap
+code will be unaffected.
+If the disk does not already have a label, the
+.Fl r
+flag must be used.
+In either case, the kernel's in-core label is replaced.
+.Pp
+An existing disk label may be edited by using the
+.Fl e
+flag.
+The label is read from the in-core kernel copy,
+or directly from the disk if the
+.Fl r
+flag is also given.
+The label is formatted and then supplied to an editor for changes.
+If no editor is specified in an
+.Ev EDITOR
+environment variable,
+.Xr vi 1
+is used.
+When the editor terminates, the formatted label is reread
+and used to rewrite the disk label.
+Existing bootstrap code is unchanged regardless of whether
+.Fl r
+was specified.
+.Pp
+With the
+.Fl R
+flag,
+.Nm disklabel
+is capable of restoring a disk label that was formatted
+in a prior operation and saved in an ascii file.
+The prototype file used to create the label should be in the same format
+as that produced when reading or editing a label.
+Comments are delimited by
+.Ar \&#
+and newline.
+As with
+.Fl w ,
+any existing bootstrap code will be clobbered if
+.Fl r
+is specified and will be unaffected otherwise.
+.Pp
+The
+.Fl NW
+flags for
+.Nm disklabel
+explicitly disallow and
+allow, respectively, writing of the pack label area on the selected disk.
+.Pp
+The final three forms of
+.Nm disklabel
+are used to install boostrap code on machines where the bootstrap is part
+of the label.
+The bootstrap code is comprised of one or two boot programs depending on
+the machine.
+The
+.Fl B
+option is used to denote that bootstrap code is to be installed.
+The
+.Fl r
+flag is implied by
+.Fl B
+and never needs to be specified.
+The name of the boot program(s) to be installed can be selected in a
+variety of ways.
+First, the names can be specified explicitly via the
+.Fl b
+and
+.Fl s
+flags.
+On machines with only a single level of boot program,
+.Fl b
+is the name of that program.
+For machines with a two-level bootstrap,
+.Fl b
+indicates the primary boot program and
+.Fl s
+the secondary boot program.
+If the names are not explicitly given, standard boot programs will be used.
+The boot programs are located in
+.Pa /usr/mdec .
+The names of the programs are taken from the ``b0'' and ``b1'' parameters
+of the
+.Xr disktab 5
+entry for the disk if
+.Ar disktype
+was given and its disktab entry exists and includes those parameters.
+Otherwise, boot program names are derived from the name of the disk.
+These names are of the form
+.Pa basename Ns boot
+for the primary (or only) bootstrap, and
+.Pf boot Pa basename
+for the secondary bootstrap;
+for example,
+.Pa /usr/mdec/sdboot
+and
+.Pa /usr/mdec/bootsd
+if the disk device is
+.Em sd0 .
+.Pp
+The first of the three boot-installation forms is used to install
+bootstrap code without changing the existing label.
+It is essentially a read command with respect to the disk label
+itself and all options are related to the specification of the boot
+program as described previously.
+The final two forms are analogous to the basic write and restore versions
+except that they will install bootstrap code in addition to a new label.
+.Sh FILES
+.Bl -tag -width Pa -compact
+.It Pa /etc/disktab
+.It Pa /usr/mdec/ Ns Em xx Ns boot
+.It Pa /usr/mdec/boot Ns Em xx
+.El
+.Sh EXAMPLES
+.Dl disklabel sd0
+.Pp
+Display the in-core label for sd0 as obtained via
+.Pa /dev/rsd0c .
+.Pp
+.Dl disklabel -w -r /dev/rsd0c sd2212 foo
+.Pp
+Create a label for sd0 based on information for ``sd2212'' found in
+.Pa /etc/disktab .
+Any existing bootstrap code will be clobbered.
+.Pp
+.Dl disklabel -e -r sd0
+.Pp
+Read the on-disk label for sd0, edit it and reinstall in-core as well
+as on-disk.
+Existing bootstrap code is unaffected.
+.Pp
+.Dl disklabel -R sd0 mylabel
+.Pp
+Restore the on-disk and in-core label for sd0 from information in
+.Pa mylabel .
+Existing bootstrap code is unaffected.
+.Pp
+.Dl disklabel -B sd0
+.Pp
+Install a new bootstrap on sd0.
+The boot code comes from
+.Pa /usr/mdec/sdboot
+and possibly
+.Pa /usr/mdec/bootsd .
+On-disk and in-core labels are unchanged.
+.Pp
+.Dl disklabel -w -B /dev/rsd0c -b newboot sd2212
+.Pp
+Install a new label and bootstrap.
+The label is derived from disktab information for ``sd2212'' and
+installed both in-core and on-disk.
+The bootstrap code comes from the file
+.Pa /usr/mdec/newboot .
+.Sh SEE ALSO
+.Xr disktab 5 ,
+.Xr disklabel 5
+.Sh DIAGNOSTICS
+The kernel device drivers will not allow the size of a disk partition
+to be decreased or the offset of a partition to be changed while it is open.
+Some device drivers create a label containing only a single large partition
+if a disk is unlabeled; thus, the label must be written to the ``a''
+partition of the disk while it is open.
+This sometimes requires the desired label to be set in two steps,
+the first one creating at least one other partition,
+and the second setting the label on the new partition
+while shrinking the ``a'' partition.
+.Pp
+On some machines the bootstrap code may not fit entirely in the area
+allocated for it by some filesystems.
+As a result, it may not be possible to have filesystems on some partitions
+of a ``bootable'' disk.
+When installing bootstrap code,
+.Nm disklabel
+checks for these cases.
+If the installed boot code would overlap a partition of type FS_UNUSED
+it is marked as type FS_BOOT.
+The
+.Xr newfs 8
+utility will disallow creation of filesystems on FS_BOOT partitions.
+Conversely, if a partition has a type other than FS_UNUSED or FS_BOOT,
+.Nm disklabel
+will not install bootstrap code that overlaps it.
+.Sh BUGS
+When a disk name is given without a full pathname,
+the constructed device name uses the ``a'' partition on the tahoe,
+the ``c'' partition on all others.
diff --git a/sbin/disklabel/disklabel.c b/sbin/disklabel/disklabel.c
new file mode 100644
index 00000000000..6df09b23881
--- /dev/null
+++ b/sbin/disklabel/disklabel.c
@@ -0,0 +1,1407 @@
+/* $NetBSD: disklabel.c,v 1.29 1995/06/26 23:17:26 jtc Exp $ */
+
+/*
+ * Copyright (c) 1987, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Symmetric Computer Systems.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1987, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+/* from static char sccsid[] = "@(#)disklabel.c 1.2 (Symmetric) 11/28/85"; */
+static char sccsid[] = "@(#)disklabel.c 8.2 (Berkeley) 1/7/94";
+#else
+static char rcsid[] = "$NetBSD: disklabel.c,v 1.29 1995/06/26 23:17:26 jtc Exp $";
+#endif
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#define DKTYPENAMES
+#include <sys/disklabel.h>
+
+#include <ufs/ffs/fs.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <unistd.h>
+#include <signal.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "pathnames.h"
+
+/*
+ * Disklabel: read and write disklabels.
+ * The label is usually placed on one of the first sectors of the disk.
+ * Many machines also place a bootstrap in the same area,
+ * in which case the label is embedded in the bootstrap.
+ * The bootstrap source must leave space at the proper offset
+ * for the label on such machines.
+ */
+
+#ifndef RAWPARTITION
+#define RAWPARTITION 'c'
+#endif
+
+#ifndef BBSIZE
+#define BBSIZE 8192 /* size of boot area, with label */
+#endif
+
+#ifndef NUMBOOT
+#define NUMBOOT 0
+#endif
+
+#define DEFEDITOR _PATH_VI
+
+char *dkname;
+char *specname;
+char tmpfil[] = _PATH_TMP;
+
+char namebuf[BBSIZE], *np = namebuf;
+struct disklabel lab;
+struct disklabel *readlabel(), *makebootarea();
+char bootarea[BBSIZE];
+
+#if NUMBOOT > 0
+int installboot; /* non-zero if we should install a boot program */
+char *bootbuf; /* pointer to buffer with remainder of boot prog */
+int bootsize; /* size of remaining boot program */
+char *xxboot; /* primary boot */
+char *bootxx; /* secondary boot */
+char boot0[MAXPATHLEN];
+char boot1[MAXPATHLEN];
+#endif
+
+enum {
+ UNSPEC, EDIT, READ, RESTORE, SETWRITEABLE, WRITE, WRITEBOOT
+} op = UNSPEC;
+
+int rflag;
+
+#ifdef DEBUG
+int debug;
+#define OPTIONS "BNRWb:ders:w"
+#else
+#define OPTIONS "BNRWb:ers:w"
+#endif
+
+#ifdef i386
+struct dos_partition *dosdp; /* i386 DOS partition, if found */
+struct dos_partition *readmbr __P((int));
+#endif
+
+void makelabel __P((char *, char *, struct disklabel *));
+int writelabel __P((int, char *, struct disklabel *));
+void l_perror __P((char *));
+struct disklabel *readlabel __P((int));
+struct disklabel *makebootarea __P((char *, struct disklabel *, int));
+void display __P((FILE *, struct disklabel *));
+int edit __P((struct disklabel *, int));
+int editit __P((void));
+char *skip __P((char *));
+char *word __P((char *));
+int getasciilabel __P((FILE *, struct disklabel *));
+int checklabel __P((struct disklabel *));
+void setbootflag __P((struct disklabel *));
+void usage __P((void));
+u_short dkcksum __P((struct disklabel *));
+
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ struct disklabel *lp;
+ FILE *t;
+ int ch, f, writeable, error = 0;
+
+ while ((ch = getopt(argc, argv, OPTIONS)) != -1)
+ switch (ch) {
+#if NUMBOOT > 0
+ case 'B':
+ ++installboot;
+ break;
+ case 'b':
+ xxboot = optarg;
+ break;
+#if NUMBOOT > 1
+ case 's':
+ bootxx = optarg;
+ break;
+#endif
+#endif
+ case 'N':
+ if (op != UNSPEC)
+ usage();
+ writeable = 0;
+ op = SETWRITEABLE;
+ break;
+ case 'R':
+ if (op != UNSPEC)
+ usage();
+ op = RESTORE;
+ break;
+ case 'W':
+ if (op != UNSPEC)
+ usage();
+ writeable = 1;
+ op = SETWRITEABLE;
+ break;
+ case 'e':
+ if (op != UNSPEC)
+ usage();
+ op = EDIT;
+ break;
+ case 'r':
+ ++rflag;
+ break;
+ case 'w':
+ if (op != UNSPEC)
+ usage();
+ op = WRITE;
+ break;
+#ifdef DEBUG
+ case 'd':
+ debug++;
+ break;
+#endif
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+#if NUMBOOT > 0
+ if (installboot) {
+ rflag++;
+ if (op == UNSPEC)
+ op = WRITEBOOT;
+ } else {
+ if (op == UNSPEC)
+ op = READ;
+ }
+#else
+ if (op == UNSPEC)
+ op = READ;
+#endif
+
+ if (argc < 1)
+ usage();
+
+ dkname = argv[0];
+ if (dkname[0] != '/') {
+ (void)sprintf(np, "%sr%s%c", _PATH_DEV, dkname, RAWPARTITION);
+ specname = np;
+ np += strlen(specname) + 1;
+ } else
+ specname = dkname;
+ f = open(specname, op == READ ? O_RDONLY : O_RDWR);
+ if (f < 0 && errno == ENOENT && dkname[0] != '/') {
+ (void)sprintf(specname, "%sr%s", _PATH_DEV, dkname);
+ np = namebuf + strlen(specname) + 1;
+ f = open(specname, op == READ ? O_RDONLY : O_RDWR);
+ }
+ if (f < 0)
+ err(4, "%s", specname);
+
+#ifdef i386
+ /*
+ * Check for presence of DOS partition table in
+ * master boot record. Return pointer to NetBSD/i386
+ * partition, if present. If no valid partition table,
+ * return 0. If valid partition table present, but no
+ * partition to use, return a pointer to a non-386bsd
+ * partition.
+ */
+ dosdp = readmbr(f);
+#endif
+
+ switch (op) {
+
+ case EDIT:
+ if (argc != 1)
+ usage();
+ lp = readlabel(f);
+ error = edit(lp, f);
+ break;
+
+ case READ:
+ if (argc != 1)
+ usage();
+ lp = readlabel(f);
+ display(stdout, lp);
+ error = checklabel(lp);
+ break;
+
+ case RESTORE:
+ if (argc < 2 || argc > 3)
+ usage();
+#if NUMBOOT > 0
+ if (installboot && argc == 3)
+ makelabel(argv[2], (char *)0, &lab);
+#endif
+ lp = makebootarea(bootarea, &lab, f);
+ if (!(t = fopen(argv[1], "r")))
+ err(4, "%s", argv[1]);
+ if (getasciilabel(t, lp))
+ error = writelabel(f, bootarea, lp);
+ break;
+
+ case SETWRITEABLE:
+ if (ioctl(f, DIOCWLABEL, (char *)&writeable) < 0)
+ err(4, "ioctl DIOCWLABEL");
+ break;
+
+ case WRITE:
+ if (argc < 2 || argc > 3)
+ usage();
+ makelabel(argv[1], argc == 3 ? argv[2] : (char *)0, &lab);
+ lp = makebootarea(bootarea, &lab, f);
+ *lp = lab;
+ if (checklabel(lp) == 0)
+ error = writelabel(f, bootarea, lp);
+ break;
+
+#if NUMBOOT > 0
+ case WRITEBOOT:
+ {
+ struct disklabel tlab;
+
+ lp = readlabel(f);
+ tlab = *lp;
+ if (argc == 2)
+ makelabel(argv[1], (char *)0, &lab);
+ lp = makebootarea(bootarea, &lab, f);
+ *lp = tlab;
+ if (checklabel(lp) == 0)
+ error = writelabel(f, bootarea, lp);
+ break;
+ }
+#endif
+ }
+ exit(error);
+}
+
+/*
+ * Construct a prototype disklabel from /etc/disktab. As a side
+ * effect, set the names of the primary and secondary boot files
+ * if specified.
+ */
+void
+makelabel(type, name, lp)
+ char *type, *name;
+ struct disklabel *lp;
+{
+ struct disklabel *dp;
+
+ dp = getdiskbyname(type);
+ if (dp == NULL)
+ errx(1, "unknown disk type: %s", type);
+ *lp = *dp;
+#if NUMBOOT > 0
+ /*
+ * Set bootstrap name(s).
+ * 1. If set from command line, use those,
+ * 2. otherwise, check if disktab specifies them (b0 or b1),
+ * 3. otherwise, makebootarea() will choose ones based on the name
+ * of the disk special file. E.g. /dev/ra0 -> raboot, bootra
+ */
+ if (!xxboot && lp->d_boot0) {
+ if (*lp->d_boot0 != '/')
+ (void)sprintf(boot0, "%s/%s",
+ _PATH_BOOTDIR, lp->d_boot0);
+ else
+ (void)strcpy(boot0, lp->d_boot0);
+ xxboot = boot0;
+ }
+#if NUMBOOT > 1
+ if (!bootxx && lp->d_boot1) {
+ if (*lp->d_boot1 != '/')
+ (void)sprintf(boot1, "%s/%s",
+ _PATH_BOOTDIR, lp->d_boot1);
+ else
+ (void)strcpy(boot1, lp->d_boot1);
+ bootxx = boot1;
+ }
+#endif
+#endif
+ /* d_packname is union d_boot[01], so zero */
+ memset(lp->d_packname, 0, sizeof(lp->d_packname));
+ if (name)
+ (void)strncpy(lp->d_packname, name, sizeof(lp->d_packname));
+}
+
+int
+writelabel(f, boot, lp)
+ int f;
+ char *boot;
+ struct disklabel *lp;
+{
+ int writeable;
+ off_t sectoffset = 0;
+
+#if NUMBOOT > 0
+ setbootflag(lp);
+#endif
+ lp->d_magic = DISKMAGIC;
+ lp->d_magic2 = DISKMAGIC;
+ lp->d_checksum = 0;
+ lp->d_checksum = dkcksum(lp);
+ if (rflag) {
+#ifdef i386
+ struct partition *pp = &lp->d_partitions[2];
+
+ /*
+ * If NetBSD/i386 DOS partition is missing, or if
+ * the label to be written is not within partition,
+ * prompt first. Need to allow this in case operator
+ * wants to convert the drive for dedicated use.
+ * In this case, partition 'a' had better start at 0,
+ * otherwise we reject the request as meaningless. -wfj
+ */
+ if (dosdp && dosdp->dp_typ == DOSPTYP_386BSD && pp->p_size &&
+ dosdp->dp_start == pp->p_offset) {
+ sectoffset = pp->p_offset * lp->d_secsize;
+ } else {
+ if (dosdp) {
+ int first, ch;
+
+ printf("Erase the previous contents of the disk? [n]: ");
+ fflush(stdout);
+ first = ch = getchar();
+ while (ch != '\n' && ch != EOF)
+ ch = getchar();
+ if (first != 'y' && first != 'Y')
+ exit(0);
+ }
+ sectoffset = 0;
+ }
+#endif
+
+ /*
+ * First set the kernel disk label,
+ * then write a label to the raw disk.
+ * If the SDINFO ioctl fails because it is unimplemented,
+ * keep going; otherwise, the kernel consistency checks
+ * may prevent us from changing the current (in-core)
+ * label.
+ */
+ if (ioctl(f, DIOCSDINFO, lp) < 0 &&
+ errno != ENODEV && errno != ENOTTY) {
+ l_perror("ioctl DIOCSDINFO");
+ return (1);
+ }
+ if (lseek(f, sectoffset, SEEK_SET) < 0) {
+ perror("lseek");
+ return (1);
+ }
+ /*
+ * write enable label sector before write (if necessary),
+ * disable after writing.
+ */
+ writeable = 1;
+ if (ioctl(f, DIOCWLABEL, &writeable) < 0)
+ perror("ioctl DIOCWLABEL");
+#ifdef __alpha__
+ /*
+ * The Alpha requires that the boot block be checksummed.
+ * The first 63 8-byte quantites are summed into the 64th.
+ */
+ {
+ int i;
+ u_int64_t *dp, sum;
+
+ dp = (u_int64_t *)boot;
+ sum = 0;
+ for (i = 0; i < 63; i++)
+ sum += dp[i];
+ dp[63] = sum;
+ }
+#endif
+ if (write(f, boot, lp->d_bbsize) != lp->d_bbsize) {
+ perror("write");
+ return (1);
+ }
+#if NUMBOOT > 0
+ /*
+ * Output the remainder of the disklabel
+ */
+ if (bootbuf && write(f, bootbuf, bootsize) != bootsize) {
+ perror("write");
+ return(1);
+ }
+#endif
+ writeable = 0;
+ if (ioctl(f, DIOCWLABEL, &writeable) < 0)
+ perror("ioctl DIOCWLABEL");
+ } else {
+ if (ioctl(f, DIOCWDINFO, lp) < 0) {
+ l_perror("ioctl DIOCWDINFO");
+ return (1);
+ }
+ }
+#ifdef vax
+ if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) {
+ daddr_t alt;
+ int i;
+
+ alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors;
+ for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) {
+ (void)lseek(f, (off_t)((alt + i) * lp->d_secsize),
+ SEEK_SET);
+ if (write(f, boot, lp->d_secsize) < lp->d_secsize)
+ warn("alternate label %d write", i/2);
+ }
+ }
+#endif
+ return (0);
+}
+
+void
+l_perror(s)
+ char *s;
+{
+
+ switch (errno) {
+
+ case ESRCH:
+ warnx("%s: No disk label on disk;\n"
+ "use \"disklabel -r\" to install initial label", s);
+ break;
+
+ case EINVAL:
+ warnx("%s: Label magic number or checksum is wrong!\n"
+ "(disklabel or kernel is out of date?)", s);
+ break;
+
+ case EBUSY:
+ warnx("%s: Open partition would move or shrink", s);
+ break;
+
+ case EXDEV:
+ warnx("%s: Labeled partition or 'a' partition must start at beginning of disk", s);
+ break;
+
+ default:
+ warn("%s", s);
+ break;
+ }
+}
+
+#ifdef i386
+/*
+ * Fetch DOS partition table from disk.
+ */
+struct dos_partition *
+readmbr(f)
+ int f;
+{
+ static char mbr[DEV_BSIZE];
+ struct dos_partition *dp = (struct dos_partition *)&mbr[DOSPARTOFF];
+ int part;
+
+ if (lseek(f, (off_t)DOSBBSECTOR, SEEK_SET) < 0 ||
+ read(f, mbr, sizeof(mbr)) < sizeof(mbr))
+ err(4, "can't read master boot record");
+
+ /*
+ * Don't (yet) know disk geometry (BIOS), use
+ * partition table to find NetBSD/i386 partition, and obtain
+ * disklabel from there.
+ */
+ /* Check if table is valid. */
+ for (part = 0; part < NDOSPART; part++) {
+ if ((dp[part].dp_flag & ~0x80) != 0)
+ return (0);
+ }
+ /* Find NetBSD partition. */
+ for (part = 0; part < NDOSPART; part++) {
+ if (dp[part].dp_size && dp[part].dp_typ == DOSPTYP_386BSD)
+ return (&dp[part]);
+ }
+ /* If no NetBSD partition, find first used partition. */
+ for (part = 0; part < NDOSPART; part++) {
+ if (dp[part].dp_size) {
+ warnx("warning, DOS partition table with no valid NetBSD partition");
+ return (&dp[part]);
+ }
+ }
+ /* Table appears to be empty. */
+ return (0);
+}
+#endif
+
+/*
+ * Fetch disklabel for disk.
+ * Use ioctl to get label unless -r flag is given.
+ */
+struct disklabel *
+readlabel(f)
+ int f;
+{
+ struct disklabel *lp;
+
+ if (rflag) {
+ char *msg;
+ off_t sectoffset = 0;
+
+#ifdef i386
+ if (dosdp && dosdp->dp_size && dosdp->dp_typ == DOSPTYP_386BSD)
+ sectoffset = dosdp->dp_start * DEV_BSIZE;
+#endif
+ if (lseek(f, sectoffset, SEEK_SET) < 0 ||
+ read(f, bootarea, BBSIZE) < BBSIZE)
+ err(4, "%s", specname);
+ msg = "no disk label";
+ for (lp = (struct disklabel *)bootarea;
+ lp <= (struct disklabel *)(bootarea + BBSIZE - sizeof(*lp));
+ lp = (struct disklabel *)((char *)lp + sizeof(long))) {
+ if (lp->d_magic == DISKMAGIC &&
+ lp->d_magic2 == DISKMAGIC) {
+ if (lp->d_npartitions <= MAXPARTITIONS &&
+ dkcksum(lp) == 0)
+ return (lp);
+ msg = "disk label corrupted";
+ }
+ }
+ /* lp = (struct disklabel *)(bootarea + LABELOFFSET); */
+ errx(1, msg);
+ } else {
+ lp = &lab;
+ if (ioctl(f, DIOCGDINFO, lp) < 0)
+ err(4, "ioctl DIOCGDINFO");
+ }
+ return (lp);
+}
+
+/*
+ * Construct a bootarea (d_bbsize bytes) in the specified buffer ``boot''
+ * Returns a pointer to the disklabel portion of the bootarea.
+ */
+struct disklabel *
+makebootarea(boot, dp, f)
+ char *boot;
+ struct disklabel *dp;
+ int f;
+{
+ struct disklabel *lp;
+ char *p;
+ int b;
+#if NUMBOOT > 0
+ char *dkbasename;
+ struct stat sb;
+#endif
+
+ /* XXX */
+ if (dp->d_secsize == 0) {
+ dp->d_secsize = DEV_BSIZE;
+ dp->d_bbsize = BBSIZE;
+ }
+ lp = (struct disklabel *)
+ (boot + (LABELSECTOR * dp->d_secsize) + LABELOFFSET);
+ memset(lp, 0, sizeof *lp);
+#if NUMBOOT > 0
+ /*
+ * If we are not installing a boot program but we are installing a
+ * label on disk then we must read the current bootarea so we don't
+ * clobber the existing boot.
+ */
+ if (!installboot) {
+ if (rflag) {
+ if (read(f, boot, BBSIZE) < BBSIZE)
+ err(4, "%s", specname);
+ memset(lp, 0, sizeof *lp);
+ }
+ return (lp);
+ }
+ /*
+ * We are installing a boot program. Determine the name(s) and
+ * read them into the appropriate places in the boot area.
+ */
+ if (!xxboot || !bootxx) {
+ dkbasename = np;
+ if ((p = strrchr(dkname, '/')) == NULL)
+ p = dkname;
+ else
+ p++;
+ while (*p && !isdigit(*p))
+ *np++ = *p++;
+ *np++ = '\0';
+
+ if (!xxboot) {
+ (void)sprintf(np, "%s/%sboot",
+ _PATH_BOOTDIR, dkbasename);
+ if (access(np, F_OK) < 0 && dkbasename[0] == 'r')
+ dkbasename++;
+ xxboot = np;
+ (void)sprintf(xxboot, "%s/%sboot",
+ _PATH_BOOTDIR, dkbasename);
+ np += strlen(xxboot) + 1;
+ }
+#if NUMBOOT > 1
+ if (!bootxx) {
+ (void)sprintf(np, "%s/boot%s",
+ _PATH_BOOTDIR, dkbasename);
+ if (access(np, F_OK) < 0 && dkbasename[0] == 'r')
+ dkbasename++;
+ bootxx = np;
+ (void)sprintf(bootxx, "%s/boot%s",
+ _PATH_BOOTDIR, dkbasename);
+ np += strlen(bootxx) + 1;
+ }
+#endif
+ }
+#ifdef DEBUG
+ if (debug)
+ warnx("bootstraps: xxboot = %s, bootxx = %s", xxboot,
+ bootxx ? bootxx : "NONE");
+#endif
+
+ /*
+ * Strange rules:
+ * 1. One-piece bootstrap (hp300/hp800)
+ * up to d_bbsize bytes of ``xxboot'' go in bootarea, the rest
+ * is remembered and written later following the bootarea.
+ * 2. Two-piece bootstraps (vax/i386?/mips?)
+ * up to d_secsize bytes of ``xxboot'' go in first d_secsize
+ * bytes of bootarea, remaining d_bbsize-d_secsize filled
+ * from ``bootxx''.
+ */
+ b = open(xxboot, O_RDONLY);
+ if (b < 0)
+ err(4, "%s", xxboot);
+#if NUMBOOT > 1
+ if (read(b, boot, (int)dp->d_secsize) < 0)
+ err(4, "%s", xxboot);
+ (void)close(b);
+ b = open(bootxx, O_RDONLY);
+ if (b < 0)
+ err(4, "%s", bootxx);
+ if (read(b, &boot[dp->d_secsize], (int)(dp->d_bbsize-dp->d_secsize)) < 0)
+ err(4, "%s", bootxx);
+#else
+ if (read(b, boot, (int)dp->d_bbsize) < 0)
+ err(4, "%s", xxboot);
+ (void)fstat(b, &sb);
+ bootsize = (int)sb.st_size - dp->d_bbsize;
+ if (bootsize > 0) {
+ /* XXX assume d_secsize is a power of two */
+ bootsize = (bootsize + dp->d_secsize-1) & ~(dp->d_secsize-1);
+ bootbuf = (char *)malloc((size_t)bootsize);
+ if (bootbuf == 0)
+ err(4, "%s", xxboot);
+ if (read(b, bootbuf, bootsize) < 0) {
+ free(bootbuf);
+ err(4, "%s", xxboot);
+ }
+ }
+#endif
+ (void)close(b);
+#endif
+ /*
+ * Make sure no part of the bootstrap is written in the area
+ * reserved for the label.
+ */
+ for (p = (char *)lp; p < (char *)lp + sizeof(struct disklabel); p++)
+ if (*p)
+ errx(2, "Bootstrap doesn't leave room for disk label");
+ return (lp);
+}
+
+void
+display(f, lp)
+ FILE *f;
+ struct disklabel *lp;
+{
+ int i, j;
+ struct partition *pp;
+
+ fprintf(f, "# %s:\n", specname);
+ if ((unsigned) lp->d_type < DKMAXTYPES)
+ fprintf(f, "type: %s\n", dktypenames[lp->d_type]);
+ else
+ fprintf(f, "type: %d\n", lp->d_type);
+ fprintf(f, "disk: %.*s\n", sizeof(lp->d_typename), lp->d_typename);
+ fprintf(f, "label: %.*s\n", sizeof(lp->d_packname), lp->d_packname);
+ fprintf(f, "flags:");
+ if (lp->d_flags & D_REMOVABLE)
+ fprintf(f, " removable");
+ if (lp->d_flags & D_ECC)
+ fprintf(f, " ecc");
+ if (lp->d_flags & D_BADSECT)
+ fprintf(f, " badsect");
+ fprintf(f, "\n");
+ fprintf(f, "bytes/sector: %d\n", lp->d_secsize);
+ fprintf(f, "sectors/track: %d\n", lp->d_nsectors);
+ fprintf(f, "tracks/cylinder: %d\n", lp->d_ntracks);
+ fprintf(f, "sectors/cylinder: %d\n", lp->d_secpercyl);
+ fprintf(f, "cylinders: %d\n", lp->d_ncylinders);
+ fprintf(f, "rpm: %d\n", lp->d_rpm);
+ fprintf(f, "interleave: %d\n", lp->d_interleave);
+ fprintf(f, "trackskew: %d\n", lp->d_trackskew);
+ fprintf(f, "cylinderskew: %d\n", lp->d_cylskew);
+ fprintf(f, "headswitch: %d\t\t# milliseconds\n", lp->d_headswitch);
+ fprintf(f, "track-to-track seek: %d\t# milliseconds\n", lp->d_trkseek);
+ fprintf(f, "drivedata: ");
+ for (i = NDDATA - 1; i >= 0; i--)
+ if (lp->d_drivedata[i])
+ break;
+ if (i < 0)
+ i = 0;
+ for (j = 0; j <= i; j++)
+ fprintf(f, "%d ", lp->d_drivedata[j]);
+ fprintf(f, "\n\n%d partitions:\n", lp->d_npartitions);
+ fprintf(f,
+ "# size offset fstype [fsize bsize cpg]\n");
+ pp = lp->d_partitions;
+ for (i = 0; i < lp->d_npartitions; i++, pp++) {
+ if (pp->p_size) {
+ fprintf(f, " %c: %8d %8d ", 'a' + i,
+ pp->p_size, pp->p_offset);
+ if ((unsigned) pp->p_fstype < FSMAXTYPES)
+ fprintf(f, "%8.8s", fstypenames[pp->p_fstype]);
+ else
+ fprintf(f, "%8d", pp->p_fstype);
+ switch (pp->p_fstype) {
+
+ case FS_UNUSED: /* XXX */
+ fprintf(f, " %5d %5d %5.5s ",
+ pp->p_fsize, pp->p_fsize * pp->p_frag, "");
+ break;
+
+ case FS_BSDFFS:
+ fprintf(f, " %5d %5d %5d ",
+ pp->p_fsize, pp->p_fsize * pp->p_frag,
+ pp->p_cpg);
+ break;
+
+ default:
+ fprintf(f, "%20.20s", "");
+ break;
+ }
+ fprintf(f, "\t# (Cyl. %4d",
+ pp->p_offset / lp->d_secpercyl);
+ if (pp->p_offset % lp->d_secpercyl)
+ putc('*', f);
+ else
+ putc(' ', f);
+ fprintf(f, "- %d",
+ (pp->p_offset +
+ pp->p_size + lp->d_secpercyl - 1) /
+ lp->d_secpercyl - 1);
+ if (pp->p_size % lp->d_secpercyl)
+ putc('*', f);
+ fprintf(f, ")\n");
+ }
+ }
+ fflush(f);
+}
+
+int
+edit(lp, f)
+ struct disklabel *lp;
+ int f;
+{
+ int first, ch;
+ struct disklabel label;
+ FILE *fd;
+ char *mktemp();
+
+ (void) mktemp(tmpfil);
+ fd = fopen(tmpfil, "w");
+ if (fd == NULL) {
+ warn("%s", tmpfil);
+ return (1);
+ }
+ (void)fchmod(fileno(fd), 0600);
+ display(fd, lp);
+ fclose(fd);
+ for (;;) {
+ if (!editit())
+ break;
+ fd = fopen(tmpfil, "r");
+ if (fd == NULL) {
+ warn("%s", tmpfil);
+ break;
+ }
+ memset(&label, 0, sizeof(label));
+ if (getasciilabel(fd, &label)) {
+ *lp = label;
+ if (writelabel(f, bootarea, lp) == 0) {
+ (void) unlink(tmpfil);
+ return (0);
+ }
+ }
+ printf("re-edit the label? [y]: ");
+ fflush(stdout);
+ first = ch = getchar();
+ while (ch != '\n' && ch != EOF)
+ ch = getchar();
+ if (first == 'n' || first == 'N')
+ break;
+ }
+ (void)unlink(tmpfil);
+ return (1);
+}
+
+int
+editit()
+{
+ int pid, xpid;
+ int stat;
+ extern char *getenv();
+ sigset_t sigset, osigset;
+
+ sigemptyset(&sigset);
+ sigaddset(&sigset, SIGINT);
+ sigaddset(&sigset, SIGQUIT);
+ sigaddset(&sigset, SIGHUP);
+ sigprocmask(SIG_BLOCK, &sigset, &osigset);
+ while ((pid = fork()) < 0) {
+ if (errno != EAGAIN) {
+ sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0);
+ warn("fork");
+ return (0);
+ }
+ sleep(1);
+ }
+ if (pid == 0) {
+ char *ed;
+
+ sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0);
+ setgid(getgid());
+ setuid(getuid());
+ if ((ed = getenv("EDITOR")) == (char *)0)
+ ed = DEFEDITOR;
+ execlp(ed, ed, tmpfil, 0);
+ perror(ed);
+ exit(1);
+ }
+ while ((xpid = wait(&stat)) >= 0)
+ if (xpid == pid)
+ break;
+ sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0);
+ return(!stat);
+}
+
+char *
+skip(cp)
+ char *cp;
+{
+
+ cp += strspn(cp, " \t");
+ if (*cp == '\0')
+ return (NULL);
+ return (cp);
+}
+
+char *
+word(cp)
+ char *cp;
+{
+
+ cp += strcspn(cp, " \t");
+ if (*cp == '\0')
+ return (NULL);
+ *cp++ = '\0';
+ cp += strspn(cp, " \t");
+ if (*cp == '\0')
+ return (NULL);
+ return (cp);
+}
+
+/*
+ * Read an ascii label in from fd f,
+ * in the same format as that put out by display(),
+ * and fill in lp.
+ */
+int
+getasciilabel(f, lp)
+ FILE *f;
+ struct disklabel *lp;
+{
+ char **cpp, *cp;
+ struct partition *pp;
+ char *tp, *s, line[BUFSIZ];
+ int v, lineno = 0, errors = 0;
+
+ lp->d_bbsize = BBSIZE; /* XXX */
+ lp->d_sbsize = SBSIZE; /* XXX */
+ while (fgets(line, sizeof(line) - 1, f)) {
+ lineno++;
+ if (cp = strpbrk(line, "#\r\n"))
+ *cp = '\0';
+ cp = skip(line);
+ if (cp == NULL)
+ continue;
+ tp = strchr(cp, ':');
+ if (tp == NULL) {
+ warnx("line %d: syntax error", lineno);
+ errors++;
+ continue;
+ }
+ *tp++ = '\0', tp = skip(tp);
+ if (!strcmp(cp, "type")) {
+ if (tp == NULL)
+ tp = "unknown";
+ cpp = dktypenames;
+ for (; cpp < &dktypenames[DKMAXTYPES]; cpp++)
+ if ((s = *cpp) && !strcmp(s, tp)) {
+ lp->d_type = cpp - dktypenames;
+ goto next;
+ }
+ v = atoi(tp);
+ if ((unsigned)v >= DKMAXTYPES)
+ warnx("line %d: warning, unknown disk type: %s",
+ lineno, tp);
+ lp->d_type = v;
+ continue;
+ }
+ if (!strcmp(cp, "flags")) {
+ for (v = 0; (cp = tp) && *cp != '\0';) {
+ tp = word(cp);
+ if (!strcmp(cp, "removable"))
+ v |= D_REMOVABLE;
+ else if (!strcmp(cp, "ecc"))
+ v |= D_ECC;
+ else if (!strcmp(cp, "badsect"))
+ v |= D_BADSECT;
+ else {
+ warnx("line %d: bad flag: %s",
+ lineno, cp);
+ errors++;
+ }
+ }
+ lp->d_flags = v;
+ continue;
+ }
+ if (!strcmp(cp, "drivedata")) {
+ int i;
+
+ for (i = 0; (cp = tp) && *cp != '\0' && i < NDDATA;) {
+ lp->d_drivedata[i++] = atoi(cp);
+ tp = word(cp);
+ }
+ continue;
+ }
+ if (sscanf(cp, "%d partitions", &v) == 1) {
+ if (v == 0 || (unsigned)v > MAXPARTITIONS) {
+ warnx("line %d: bad # of partitions", lineno);
+ lp->d_npartitions = MAXPARTITIONS;
+ errors++;
+ } else
+ lp->d_npartitions = v;
+ continue;
+ }
+ if (tp == NULL)
+ tp = "";
+ if (!strcmp(cp, "disk")) {
+ strncpy(lp->d_typename, tp, sizeof (lp->d_typename));
+ continue;
+ }
+ if (!strcmp(cp, "label")) {
+ strncpy(lp->d_packname, tp, sizeof (lp->d_packname));
+ continue;
+ }
+ if (!strcmp(cp, "bytes/sector")) {
+ v = atoi(tp);
+ if (v <= 0 || (v % 512) != 0) {
+ warnx("line %d: bad %s: %s", lineno, cp, tp);
+ errors++;
+ } else
+ lp->d_secsize = v;
+ continue;
+ }
+ if (!strcmp(cp, "sectors/track")) {
+ v = atoi(tp);
+ if (v <= 0) {
+ warnx("line %d: bad %s: %s", lineno, cp, tp);
+ errors++;
+ } else
+ lp->d_nsectors = v;
+ continue;
+ }
+ if (!strcmp(cp, "sectors/cylinder")) {
+ v = atoi(tp);
+ if (v <= 0) {
+ warnx("line %d: bad %s: %s", lineno, cp, tp);
+ errors++;
+ } else
+ lp->d_secpercyl = v;
+ continue;
+ }
+ if (!strcmp(cp, "tracks/cylinder")) {
+ v = atoi(tp);
+ if (v <= 0) {
+ warnx("line %d: bad %s: %s", lineno, cp, tp);
+ errors++;
+ } else
+ lp->d_ntracks = v;
+ continue;
+ }
+ if (!strcmp(cp, "cylinders")) {
+ v = atoi(tp);
+ if (v <= 0) {
+ warnx("line %d: bad %s: %s", lineno, cp, tp);
+ errors++;
+ } else
+ lp->d_ncylinders = v;
+ continue;
+ }
+ if (!strcmp(cp, "rpm")) {
+ v = atoi(tp);
+ if (v <= 0) {
+ warnx("line %d: bad %s: %s", lineno, cp, tp);
+ errors++;
+ } else
+ lp->d_rpm = v;
+ continue;
+ }
+ if (!strcmp(cp, "interleave")) {
+ v = atoi(tp);
+ if (v <= 0) {
+ warnx("line %d: bad %s: %s", lineno, cp, tp);
+ errors++;
+ } else
+ lp->d_interleave = v;
+ continue;
+ }
+ if (!strcmp(cp, "trackskew")) {
+ v = atoi(tp);
+ if (v < 0) {
+ warnx("line %d: bad %s: %s", lineno, cp, tp);
+ errors++;
+ } else
+ lp->d_trackskew = v;
+ continue;
+ }
+ if (!strcmp(cp, "cylinderskew")) {
+ v = atoi(tp);
+ if (v < 0) {
+ warnx("line %d: bad %s: %s", lineno, cp, tp);
+ errors++;
+ } else
+ lp->d_cylskew = v;
+ continue;
+ }
+ if (!strcmp(cp, "headswitch")) {
+ v = atoi(tp);
+ if (v < 0) {
+ warnx("line %d: bad %s: %s", lineno, cp, tp);
+ errors++;
+ } else
+ lp->d_headswitch = v;
+ continue;
+ }
+ if (!strcmp(cp, "track-to-track seek")) {
+ v = atoi(tp);
+ if (v < 0) {
+ warnx("line %d: bad %s: %s", lineno, cp, tp);
+ errors++;
+ } else
+ lp->d_trkseek = v;
+ continue;
+ }
+ if ('a' <= *cp && *cp <= 'z' && cp[1] == '\0') {
+ unsigned part = *cp - 'a';
+
+ if (part > lp->d_npartitions) {
+ warnx("line %d: bad partition name: %s",
+ lineno, cp);
+ errors++;
+ continue;
+ }
+ pp = &lp->d_partitions[part];
+#define NXTNUM(n) { \
+ if (tp == NULL) { \
+ warnx("line %d: too few fields", lineno); \
+ errors++; \
+ break; \
+ } else \
+ cp = tp, tp = word(cp), (n) = atoi(cp); \
+}
+ NXTNUM(v);
+ if (v < 0) {
+ warnx("line %d: bad partition size: %s",
+ lineno, cp);
+ errors++;
+ } else
+ pp->p_size = v;
+ NXTNUM(v);
+ if (v < 0) {
+ warnx("line %d: bad partition offset: %s",
+ lineno, cp);
+ errors++;
+ } else
+ pp->p_offset = v;
+ cp = tp, tp = word(cp);
+ cpp = fstypenames;
+ for (; cpp < &fstypenames[FSMAXTYPES]; cpp++)
+ if ((s = *cpp) && !strcmp(s, cp)) {
+ pp->p_fstype = cpp - fstypenames;
+ goto gottype;
+ }
+ if (isdigit(*cp))
+ v = atoi(cp);
+ else
+ v = FSMAXTYPES;
+ if ((unsigned)v >= FSMAXTYPES) {
+ warnx("line %d: warning, unknown filesystem type: %s",
+ lineno, cp);
+ v = FS_UNUSED;
+ }
+ pp->p_fstype = v;
+ gottype:
+ switch (pp->p_fstype) {
+
+ case FS_UNUSED: /* XXX */
+ NXTNUM(pp->p_fsize);
+ if (pp->p_fsize == 0)
+ break;
+ NXTNUM(v);
+ pp->p_frag = v / pp->p_fsize;
+ break;
+
+ case FS_BSDFFS:
+ NXTNUM(pp->p_fsize);
+ if (pp->p_fsize == 0)
+ break;
+ NXTNUM(v);
+ pp->p_frag = v / pp->p_fsize;
+ NXTNUM(pp->p_cpg);
+ break;
+
+ default:
+ break;
+ }
+ continue;
+ }
+ warnx("line %d: unknown field: %s", lineno, cp);
+ errors++;
+ next:
+ ;
+ }
+ errors += checklabel(lp);
+ return (errors == 0);
+}
+
+/*
+ * Check disklabel for errors and fill in
+ * derived fields according to supplied values.
+ */
+int
+checklabel(lp)
+ struct disklabel *lp;
+{
+ struct partition *pp;
+ int i, errors = 0;
+ char part;
+
+ if (lp->d_secsize == 0) {
+ warnx("sector size %d", lp->d_secsize);
+ return (1);
+ }
+ if (lp->d_nsectors == 0) {
+ warnx("sectors/track %d", lp->d_nsectors);
+ return (1);
+ }
+ if (lp->d_ntracks == 0) {
+ warnx("tracks/cylinder %d", lp->d_ntracks);
+ return (1);
+ }
+ if (lp->d_ncylinders == 0) {
+ warnx("cylinders/unit %d", lp->d_ncylinders);
+ errors++;
+ }
+ if (lp->d_rpm == 0)
+ warnx("warning, revolutions/minute %d", lp->d_rpm);
+ if (lp->d_secpercyl == 0)
+ lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
+ if (lp->d_secperunit == 0)
+ lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders;
+#ifdef i386__notyet
+ if (dosdp && dosdp->dp_size && dosdp->dp_typ == DOSPTYP_386BSD
+ && lp->d_secperunit > dosdp->dp_start + dosdp->dp_size) {
+ warnx("exceeds DOS partition size");
+ errors++;
+ lp->d_secperunit = dosdp->dp_start + dosdp->dp_size;
+ }
+ /* XXX should also check geometry against BIOS's idea */
+#endif
+ if (lp->d_bbsize == 0) {
+ warnx("boot block size %d", lp->d_bbsize);
+ errors++;
+ } else if (lp->d_bbsize % lp->d_secsize)
+ warnx("warning, boot block size %% sector-size != 0");
+ if (lp->d_sbsize == 0) {
+ warnx("super block size %d", lp->d_sbsize);
+ errors++;
+ } else if (lp->d_sbsize % lp->d_secsize)
+ warnx("warning, super block size %% sector-size != 0");
+ if (lp->d_npartitions > MAXPARTITIONS)
+ warnx("warning, number of partitions (%d) > MAXPARTITIONS (%d)",
+ lp->d_npartitions, MAXPARTITIONS);
+ for (i = 0; i < lp->d_npartitions; i++) {
+ part = 'a' + i;
+ pp = &lp->d_partitions[i];
+ if (pp->p_size == 0 && pp->p_offset != 0)
+ warnx("warning, partition %c: size 0, but offset %d",
+ part, pp->p_offset);
+#ifdef notdef
+ if (pp->p_size % lp->d_secpercyl)
+ warnx("warning, partition %c: size %% cylinder-size != 0",
+ part);
+ if (pp->p_offset % lp->d_secpercyl)
+ warnx("warning, partition %c: offset %% cylinder-size != 0",
+ part);
+#endif
+ if (pp->p_offset > lp->d_secperunit) {
+ warnx("partition %c: offset past end of unit", part);
+ errors++;
+ }
+ if (pp->p_offset + pp->p_size > lp->d_secperunit) {
+ warnx("partition %c: partition extends past end of unit",
+ part);
+ errors++;
+ }
+ }
+ for (; i < MAXPARTITIONS; i++) {
+ part = 'a' + i;
+ pp = &lp->d_partitions[i];
+ if (pp->p_size || pp->p_offset)
+ warnx("warning, unused partition %c: size %d offset %d",
+ 'a' + i, pp->p_size, pp->p_offset);
+ }
+ return (errors);
+}
+
+#if NUMBOOT > 0
+/*
+ * If we are installing a boot program that doesn't fit in d_bbsize
+ * we need to mark those partitions that the boot overflows into.
+ * This allows newfs to prevent creation of a filesystem where it might
+ * clobber bootstrap code.
+ */
+void
+setbootflag(lp)
+ struct disklabel *lp;
+{
+ struct partition *pp;
+ int i, errors = 0;
+ char part;
+ u_long boffset;
+
+ if (bootbuf == 0)
+ return;
+ boffset = bootsize / lp->d_secsize;
+ for (i = 0; i < lp->d_npartitions; i++) {
+ part = 'a' + i;
+ pp = &lp->d_partitions[i];
+ if (pp->p_size == 0)
+ continue;
+ if (boffset <= pp->p_offset) {
+ if (pp->p_fstype == FS_BOOT)
+ pp->p_fstype = FS_UNUSED;
+ } else if (pp->p_fstype != FS_BOOT) {
+ if (pp->p_fstype != FS_UNUSED) {
+ warnx("boot overlaps used partition %c",
+ part);
+ errors++;
+ } else {
+ pp->p_fstype = FS_BOOT;
+ warnx("warning, boot overlaps partition %c, %s",
+ part, "marked as FS_BOOT");
+ }
+ }
+ }
+ if (errors)
+ errx(4, "cannot install boot program");
+}
+#endif
+
+void
+usage()
+{
+
+#if NUMBOOT > 0
+ fprintf(stderr,
+"%s\n\t%s\n%s\n\t%s\n%s\n\t%s\n%s\n\t%s\n%s\n\t%s\n%s\n\t%s\n%s\n\t%s\n%s\n\t%s\n",
+"usage: disklabel [-r] disk",
+ "(to read label)",
+"or disklabel -w [-r] disk type [ packid ]",
+ "(to write label with existing boot program)",
+"or disklabel -e [-r] disk",
+ "(to edit label)",
+"or disklabel -R [-r] disk protofile",
+ "(to restore label with existing boot program)",
+#if NUMBOOT > 1
+"or disklabel -B [ -b xxboot [ -s bootxx ] ] disk [ type ]",
+ "(to install boot program with existing label)",
+"or disklabel -w -B [ -b xxboot [ -s bootxx ] ] disk type [ packid ]",
+ "(to write label and boot program)",
+"or disklabel -R -B [ -b xxboot [ -s bootxx ] ] disk protofile [ type ]",
+ "(to restore label and boot program)",
+#else
+"or disklabel -B [ -b bootprog ] disk [ type ]",
+ "(to install boot program with existing on-disk label)",
+"or disklabel -w -B [ -b bootprog ] disk type [ packid ]",
+ "(to write label and install boot program)",
+"or disklabel -R -B [ -b bootprog ] disk protofile [ type ]",
+ "(to restore label and install boot program)",
+#endif
+"or disklabel [-NW] disk",
+ "(to write disable/enable label)");
+#else
+ fprintf(stderr, "%-43s%s\n%-43s%s\n%-43s%s\n%-43s%s\n%-43s%s\n",
+"usage: disklabel [-r] disk", "(to read label)",
+"or disklabel -w [-r] disk type [ packid ]", "(to write label)",
+"or disklabel -e [-r] disk", "(to edit label)",
+"or disklabel -R [-r] disk protofile", "(to restore label)",
+"or disklabel [-NW] disk", "(to write disable/enable label)");
+#endif
+ exit(1);
+}
diff --git a/sbin/disklabel/dkcksum.c b/sbin/disklabel/dkcksum.c
new file mode 100644
index 00000000000..851a55a7e7d
--- /dev/null
+++ b/sbin/disklabel/dkcksum.c
@@ -0,0 +1,59 @@
+/* $NetBSD: dkcksum.c,v 1.6 1995/03/18 14:54:42 cgd Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)dkcksum.c 8.1 (Berkeley) 6/5/93";
+#else
+static char rcsid[] = "$NetBSD: dkcksum.c,v 1.6 1995/03/18 14:54:42 cgd Exp $";
+#endif
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/disklabel.h>
+
+u_short
+dkcksum(lp)
+ register struct disklabel *lp;
+{
+ register u_short *start, *end;
+ register u_short sum = 0;
+
+ start = (u_short *)lp;
+ end = (u_short *)&lp->d_partitions[lp->d_npartitions];
+ while (start < end)
+ sum ^= *start++;
+ return (sum);
+}
diff --git a/sbin/disklabel/pathnames.h b/sbin/disklabel/pathnames.h
new file mode 100644
index 00000000000..2123e5ffe7c
--- /dev/null
+++ b/sbin/disklabel/pathnames.h
@@ -0,0 +1,42 @@
+/* $NetBSD: pathnames.h,v 1.6 1995/03/18 14:54:43 cgd Exp $ */
+
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)pathnames.h 8.1 (Berkeley) 6/5/93
+ */
+
+#include <paths.h>
+
+#define _PATH_BOOTDIR "/usr/mdec"
+#undef _PATH_TMP
+#define _PATH_TMP "/tmp/EdDk.aXXXXXX"