Subject: Disklabels arrive for 2.11BSD (#252 part 3 of 18)
Index:	sys,bin,usr.lib,(many more)/<many> 2.11BSD

Description:
	The moving the partitions tables out of the disk drivers and to
	a disklabel residing on the media has been on the wish list for
	many many years.

	Disklabels have finally arrived for 2.11BSD!

Repeat-By:
	Observation.  Also a reading of the setup and installation
	documentation for previous 2BSD releases (2.9, 2.10, 2.11)
	all have a paragraph similar to this present:

"It is possible to change the partitions by changing the code for the
table in the disk driver.  Since it's desirable to do this, these tables
really should be read off each pack...."

Fix:
	This is part 3 of 18.  Gather all parts before doing anything
	except reading the instructions which are in #250 (part 1).

	Updated by this part are:

/usr/src/bin/disklabel
/usr/src/bin/Makefile

	'disklabel' is new.  It is added to the system by unpacking
	the shar archive included below.

	'Makefile' is updated to add the disklabel program.

	Cut where indicated below and save to a file (/tmp/252).  Then:

		cd /tmp
		sh 252
		sh bin.shar
		patch -p0 < bin.patch
		rm bin.shar 252 bin.patch

------------------------cut here---------------------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	bin.patch
#	bin.shar
# This archive created: Mon Jul 10 22:17:06 1995
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f 'bin.patch'
then
	echo shar: "will not over-write existing file 'bin.patch'"
else
sed 's/^Y//' << \SHAR_EOF > 'bin.patch'
Y*** /usr/src/bin/Makefile.old	Tue May  2 23:39:43 1995
Y--- /usr/src/bin/Makefile	Fri Jun  9 22:51:36 1995
Y***************
Y*** 3,9 ****
Y  # All rights reserved.  The Berkeley software License Agreement
Y  # specifies the terms and conditions for redistribution.
Y  #
Y! #	@(#)Makefile	5.19.6 (2.11BSD GTE) 1995/05/02
Y  #
Y  DESTDIR=
Y  CFLAGS=	-O
Y--- 3,9 ----
Y  # All rights reserved.  The Berkeley software License Agreement
Y  # specifies the terms and conditions for redistribution.
Y  #
Y! #	@(#)Makefile	5.19.7 (2.11BSD GTE) 1995/06/09
Y  #
Y  DESTDIR=
Y  CFLAGS=	-O
Y***************
Y*** 11,18 ****
Y  
Y  # Programs that live in subdirectories, and have makefiles of their own.
Y  #
Y! SUBDIR=	adb ar as awk chflags chpass csh diff hostname ld login ls make nm \
Y! 	passwd sed sh sysctl test tp
Y  
Y  # Shell scripts that need only be installed and are never removed.
Y  #
Y--- 11,18 ----
Y  
Y  # Programs that live in subdirectories, and have makefiles of their own.
Y  #
Y! SUBDIR=	adb ar as awk chflags chpass csh diff disklabel hostname ld login \
Y! 	ls make nm passwd sed sh sysctl test tp
Y  
Y  # Shell scripts that need only be installed and are never removed.
Y  #
SHAR_EOF
fi
if test -f 'bin.shar'
then
	echo shar: "will not over-write existing file 'bin.shar'"
else
sed 's/^Y//' << \SHAR_EOF > 'bin.shar'
Y#! /bin/sh
Y# This is a shell archive, meaning:
Y# 1. Remove everything above the #! /bin/sh line.
Y# 2. Save the resulting text in a file.
Y# 3. Execute the file with /bin/sh (not csh) to create:
Y#	/usr/src/bin/disklabel
Y# This archive created: Mon Jul 10 22:16:07 1995
Yexport PATH; PATH=/bin:/usr/bin:$PATH
Yif test ! -d '/usr/src/bin/disklabel'
Ythen
Y	mkdir '/usr/src/bin/disklabel'
Yfi
Ycd '/usr/src/bin/disklabel'
Yif test -f 'Makefile'
Ythen
Y	echo shar: "will not over-write existing file 'Makefile'"
Yelse
Ysed 's/^X//' << \SHAR_EOF > 'Makefile'
YX#	@(#)Makefile	1.0 (2.11BSD) 1995/04/10
YX
YXDESTDIR=
YXCFLAGS=-O
YXSEPFLAG=-i
YXMANDIR=/usr/man/cat
YX
YXall: disklabel disklabel.5.0 disklabel.0
YX
YXdisklabel: disklabel.o
YX	cc ${CFLAGS} ${SEPFLAG} -o $@ $@.o -lutil
YX
YXinstall: all
YX	install -s -c -o bin -g operator -m 2550 disklabel \
YX			${DESTDIR}/bin/disklabel
YX	install -c -o bin -g bin -m 444 disklabel.5.0 \
YX			${DESTDIR}${MANDIR}5/disklabel.0
YX	install -c -o bin -g bin -m 444 disklabel.0 \
YX			${DESTDIR}/${MANDIR}8/disklabel.0
YX
YXclean:
YX	rm -f *.o *.0 *.core disklabel
YX
YXdisklabel.0: disklabel.8
YX	/usr/man/manroff disklabel.8 > disklabel.0
YX
YXdisklabel.5.0: disklabel.5.5
YX	/usr/man/manroff disklabel.5.5 > disklabel.5.0
YSHAR_EOF
Yfi
Yif test -f 'disklabel.5.5'
Ythen
Y	echo shar: "will not over-write existing file 'disklabel.5.5'"
Yelse
Ysed 's/^X//' << \SHAR_EOF > 'disklabel.5.5'
YX.\" Copyright (c) 1987, 1991, 1993
YX.\"	The Regents of the University of California.  All rights reserved.
YX.\"
YX.\" This code is derived from software contributed to Berkeley by
YX.\" Symmetric Computer Systems.
YX.\"
YX.\" Redistribution and use in source and binary forms, with or without
YX.\" modification, are permitted provided that the following conditions
YX.\" are met:
YX.\" 1. Redistributions of source code must retain the above copyright
YX.\"    notice, this list of conditions and the following disclaimer.
YX.\" 2. Redistributions in binary form must reproduce the above copyright
YX.\"    notice, this list of conditions and the following disclaimer in the
YX.\"    documentation and/or other materials provided with the distribution.
YX.\" 3. All advertising materials mentioning features or use of this software
YX.\"    must display the following acknowledgement:
YX.\"	This product includes software developed by the University of
YX.\"	California, Berkeley and its contributors.
YX.\" 4. Neither the name of the University nor the names of its contributors
YX.\"    may be used to endorse or promote products derived from this software
YX.\"    without specific prior written permission.
YX.\"
YX.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
YX.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
YX.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
YX.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
YX.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
YX.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
YX.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
YX.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
YX.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
YX.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
YX.\" SUCH DAMAGE.
YX.\"
YX.\"     @(#)disklabel.5.5	8.1.1 (2.11BSD) 1995/04/21
YX.\"
YX.TH DISKLABEL 5 "April 21, 1995"
YX.UC 2
YX.SH NAME
YXdisklabel \- disk pack label
YX.SH SYNOPSIS
YX.B #include <sys/disklabel.h>
YX.SH DESCRIPTION
YXEach disk or disk pack on a system may contain a disk label
YXwhich provides detailed information
YXabout the geometry of the disk and the partitions into which the disk
YXis divided.
YXIt should be initialized when the disk is formatted,
YXand may be changed later with the
YX.IR disklabel (8)
YXprogram.
YXThis information is used by the system disk driver and by the bootstrap
YXprogram to determine how to program the drive
YXand where to find the filesystems on the disk partitions.
YXAdditional information is used by the filesystem in order
YXto use the disk most efficiently and to locate important filesystem information.
YXThe description of each partition contains an identifier for the partition
YXtype (standard filesystem, swap area, etc.).
YXThe filesystem updates the in-core copy of the label if it contains
YXincomplete information about the filesystem.
YX.PP
YXThe label is located in sector number
YX.B LABELSECTOR
YXof the drive, usually sector 0 where it may be found
YXwithout any information about the disk geometry.
YXIt is at an offset
YX.B LABELOFFSET
YXfrom the beginning of the sector, to allow room for the initial bootstrap.
YXThe disk sector containing the label is normally made read-only
YXso that it is not accidentally overwritten by pack-to-pack copies
YXor swap operations;
YXthe
YX.B DIOCWLABEL
YX.IR ioctl (2),
YXwhich is done as needed by the
YX.IR disklabel (8)
YXprogram.
YX.PP
YXA copy of the in-core label for a disk can be obtained with the
YX.B DIOCGDINFO
YX.IR ioctl (2);
YXthis works with a file descriptor for a block or character (``raw'') device
YXfor any partition of the disk.
YXThe in-core copy of the label is set by the 
YX.B DIOCSDINFO
YX.IR ioctl (2).
YXThe offset of a partition cannot generally be changed while it is open,
YXnor can it be made smaller while it is open.
YXOne exception is that any change is allowed if no label was found
YXon the disk, and the driver was able to construct only a skeletal label
YXwithout partition information.
YXFinally, the 
YX.B DIOCWDINFO
YX.IR ioctl (2)
YXoperation sets the in-core label and then updates the on-disk label;
YXthere must be an existing label on the disk for this operation to succeed.
YXThus, the initial label for a disk or disk pack must be installed
YXby writing to the raw disk.
YXAll of these operations are normally done using
YX.IR disklabel (8).
YX.PP
YXThe format of the disk label, as specified in
YX.I \<sys/disklabel.h\> ,
YXis:
YX.PP
YX.nf
YX/*
YX * Disk description table, see disktab(5)
YX */
YX#define	_PATH_DISKTAB	"/etc/disktab"
YX
YX/*
YX * Each disk has a label which includes information about the hardware
YX * disk geometry, filesystem partitions, and drive specific information.
YX * The label is in block 0 or 1, possibly offset from the beginning
YX * to leave room for a bootstrap, etc.
YX */
YX
YX/* These should be defined per controller/drive elsewhere, not here! */
YX#define LABELSECTOR	1				/* sector containing label */
YX#define LABELOFFSET	0				/* offset of label in sector */
YX
YX#define DISKMAGIC ((u_long) 0x82564557)	/* The disk magic number */
YX#define	MAXPARTITIONS	8
YX
YX/*
YX * 2.11BSD's disklabels are different than 4.4BSD for a couple reasons:
YX *
YX *	1) D space is precious in the 2.11 kernel.  Many of the fields do
YX *	   not need to be 'long' (or even a 'short'), a 'short' (or 'char')
YX *	   is more than adequate.  If anyone ever ports the FFS to a PDP11 
YX *	   changing the label format will be the least of the problems.
YX *
YX *	2) There is no need to support a bootblock more than 512 bytes long.
YX *	   The hardware (disk bootroms) only read the first sector, thus the
YX *	   label is always at sector 1 (the second half of the first file-
YX *	   system block).
YX *
YX * Almost all of the fields have been retained but with reduced sizes.
YX * This is for future expansion and to ease the porting of the various
YX * utilities which use the disklabel structure.  The 2.11 kernel uses 
YX * very little other than the partition tables.  Indeed only the 
YX * partition tables are resident in the kernel address space, the actual
YX * label block is allocated external to the kernel and mapped in as
YX * needed.
YX*/
YX
YXstruct disklabel {
YX	u_long	d_magic;			/* the magic number */
YX	u_char	d_type;			/* drive type */
YX	u_char	d_subtype;		/* controller/d_type specific */
YX	char		d_typename[16];	/* type name, e.g. "eagle" */
YX	/* 
YX	 * d_packname contains the pack identifier and is returned when
YX	 * the disklabel is read off the disk or in-core copy.
YX	 * d_boot0 is the (optional) name of the primary (block 0) bootstrap
YX	 * as found in /mdec.  This is returned when using
YX	 * getdiskbyname(3) to retrieve the values from /etc/disktab.
YX	 */
YX#if defined(KERNEL) || defined(STANDALONE)
YX	char	d_packname[16];		/* pack identifier */ 
YX#else
YX	union {
YX		char	un_d_packname[16];	/* pack identifier */ 
YX		char	*un_d_boot0;		/* primary bootstrap name */
YX	} d_un; 
YX#define d_packname	d_un.un_d_packname
YX#define d_boot0		d_un.un_d_boot0
YX#endif	/* ! KERNEL or STANDALONE */
YX				/* disk geometry: */
YX	u_short	d_secsize;		/* # of bytes per sector */
YX	u_short	d_nsectors;		/* # of data sectors per track */
YX	u_short	d_ntracks;		/* # of tracks per cylinder */
YX	u_short	d_ncylinders;		/* # of data cylinders per unit */
YX	u_short	d_secpercyl;		/* # of data sectors per cylinder */
YX	u_long	d_secperunit;		/* # of data sectors per unit */
YX	/*
YX	 * Spares (bad sector replacements) below
YX	 * are not counted in d_nsectors or d_secpercyl.
YX	 * Spare sectors are assumed to be physical sectors
YX	 * which occupy space at the end of each track and/or cylinder.
YX	 */
YX	u_short	d_sparespertrack;	/* # of spare sectors per track */
YX	u_short	d_sparespercyl;	/* # of spare sectors per cylinder */
YX	/*
YX	 * Alternate cylinders include maintenance, replacement,
YX	 * configuration description areas, etc.
YX	 */
YX	u_short	d_acylinders;		/* # of alt. cylinders per unit */
YX
YX			/* hardware characteristics: */
YX	/*
YX	 * d_interleave, d_trackskew and d_cylskew describe perturbations
YX	 * in the media format used to compensate for a slow controller.
YX	 * Interleave is physical sector interleave, set up by the formatter
YX	 * or controller when formatting.  When interleaving is in use,
YX	 * logically adjacent sectors are not physically contiguous,
YX	 * but instead are separated by some number of sectors.
YX	 * It is specified as the ratio of physical sectors traversed
YX	 * per logical sector.  Thus an interleave of 1:1 implies contiguous
YX	 * layout, while 2:1 implies that logical sector 0 is separated
YX	 * by one sector from logical sector 1.
YX	 * d_trackskew is the offset of sector 0 on track N
YX	 * relative to sector 0 on track N-1 on the same cylinder.
YX	 * Finally, d_cylskew is the offset of sector 0 on cylinder N
YX	 * relative to sector 0 on cylinder N-1.
YX	 */
YX	u_short	d_rpm;			/* rotational speed */
YX	u_char	d_interleave;		/* hardware sector interleave */
YX	u_char	d_trackskew;		/* sector 0 skew, per track */
YX	u_char	d_cylskew;		/* sector 0 skew, per cylinder */
YX	u_char	d_headswitch;		/* head swith time, usec */
YX	u_short	d_trkseek;		/* track-to-track seek, msec */
YX	u_short	d_flags;			/* generic flags */
YX#define NDDATA 5
YX	u_long	d_drivedata[NDDATA]; /* drive-type specific information */
YX#define NSPARE 5
YX	u_long	d_spare[NSPARE];	/* reserved for future use */
YX	u_long	d_magic2;			/* the magic number (again) */
YX	u_short	d_checksum;		/* xor of data incl. partitions */
YX
YX			/* filesystem and partition information: */
YX	u_short	d_npartitions;		/* number of partitions in following */
YX	u_short	d_bbsize;			/* size of boot area at sn0, bytes */
YX	u_short	d_sbsize;			/* max size of fs superblock, bytes */
YX	struct	partition {		/* the partition table */
YX		u_long	p_size;		/* number of sectors in partition */
YX		u_long	p_offset;		/* starting sector */
YX		u_short	p_fsize;		/* filesystem basic fragment size */
YX		u_char	p_fstype;		/* filesystem type, see below */
YX		u_char	p_frag;		/* filesystem fragments per block */
YX	} d_partitions[MAXPARTITIONS];	/* actually may be more */
YX};
YX
YX/* d_type values: */
YX#define	DTYPE_SMD		1		/* SMD, XSMD; VAX hp/up */
YX#define	DTYPE_MSCP	2		/* MSCP */
YX#define	DTYPE_DEC		3		/* other DEC (rk, rl) */
YX#define	DTYPE_SCSI	4		/* SCSI */
YX#define	DTYPE_ESDI	5		/* ESDI interface */
YX#define	DTYPE_ST506	6		/* ST506 etc. */
YX#define	DTYPE_FLOPPY	7		/* floppy */
YX
YX#ifdef DKTYPENAMES
YXstatic char *dktypenames[] = {
YX	"unknown",
YX	"SMD",
YX	"MSCP",
YX	"old DEC",
YX	"SCSI",
YX	"ESDI",
YX	"ST506",
YX	"floppy",
YX	0
YX};
YX#define DKMAXTYPES	(sizeof(dktypenames) / sizeof(dktypenames[0]) - 1)
YX#endif
YX
YX/*
YX * Filesystem type and version.
YX * Used to interpret other filesystem-specific
YX * per-partition information.
YX */
YX#define	FS_UNUSED		0		/* unused */
YX#define	FS_SWAP		1		/* swap */
YX#define	FS_V6		2		/* Sixth Edition */
YX#define	FS_V7		3		/* Seventh Edition */
YX#define	FS_SYSV		4		/* System V */
YX/*
YX * 2.11BSD uses type 5 filesystems even though block numbers are 4 bytes
YX * (rather than the packed 3 byte format) and the directory structure is
YX * that of 4.3BSD (long filenames).
YX*/
YX#define	FS_V71K		5		/* V7 with 1K blocks (4.1,2.9,2.11) */
YX#define	FS_V8		6		/* Eighth Edition, 4K blocks */
YX#define	FS_BSDFFS		7		/* 4.2BSD fast file system */
YX#define	FS_MSDOS		8		/* MSDOS file system */
YX#define	FS_BSDLFS		9		/* 4.4BSD log file system */
YX#define	FS_OTHER		10		/* in use, but unknown/unsupported */
YX#define	FS_HPFS		11		/* OS/2 high-performance filesystem */
YX#define	FS_ISO9660	12		/* ISO 9660, normally CD-ROM */
YX
YX#ifdef	DKTYPENAMES
YXstatic char *fstypenames[] = {
YX	"unused",
YX	"swap",
YX	"Version 6",
YX	"Version 7",
YX	"System V",
YX	"2.11BSD",
YX	"Eighth Edition",
YX	"4.2BSD",
YX	"MSDOS",
YX	"4.4LFS",
YX	"unknown",
YX	"HPFS",
YX	"ISO9660",
YX	0
YX};
YX#define FSMAXTYPES	(sizeof(fstypenames) / sizeof(fstypenames[0]) - 1)
YX#endif
YX
YX/*
YX * flags shared by various drives:
YX */
YX#define	D_REMOVABLE	0x01		/* removable media */
YX#define	D_ECC		0x02		/* supports ECC */
YX#define	D_BADSECT		0x04		/* supports bad sector forw. */
YX#define	D_RAMDISK		0x08		/* disk emulator */
YX
YX/*
YX * Structure used to perform a format
YX * or other raw operation, returning data
YX * and/or register values.
YX * Register identification and format
YX * are device- and driver-dependent.
YX */
YXstruct format_op {
YX	char		*df_buf;
YX	int		df_count;		/* value-result */
YX	daddr_t	df_startblk;
YX	int		df_reg[8];	/* result */
YX};
YX
YX/*
YX * Structure used internally to retrieve
YX * information about a partition on a disk.
YX */
YXstruct partinfo {
YX	struct disklabel *disklab;
YX	struct partition *part;
YX};
YX
YX/*
YX * Disk-specific ioctls.
YX */
YX		/* get and set disklabel; DIOCGPART used internally */
YX#define DIOCGDINFO	_IOR(d, 101, struct disklabel)/* get */
YX#define DIOCSDINFO	_IOW(d, 102, struct disklabel)/* set */
YX#define DIOCWDINFO	_IOW(d, 103, struct disklabel)/* set, update disk */
YX#define DIOCGPART	_IOW(d, 104, struct partinfo)	/* get partition */
YX
YX/* do format operation, read or write */
YX#define DIOCRFORMAT	_IOWR(d, 105, struct format_op)
YX#define DIOCWFORMAT	_IOWR(d, 106, struct format_op)
YX
YX#define DIOCSSTEP	_IOW(d, 107, int)		/* set step rate */
YX#define DIOCSRETRIES	_IOW(d, 108, int)	/* set # of retries */
YX#define DIOCWLABEL	_IOW(d, 109, int)		/* write en/disable label */
YX
YX#define DIOCSBAD	_IOW(d, 110, struct dkbad)	/* set kernel dkbad */
YX
YX#ifndef	KERNEL
YXstruct disklabel *getdiskbyname();
YX#endif
YX.fi
YX.SH SEE ALSO
YX.IR disklabel (8)
YSHAR_EOF
Yfi
Yif test -f 'disklabel.8'
Ythen
Y	echo shar: "will not over-write existing file 'disklabel.8'"
Yelse
Ysed 's/^X//' << \SHAR_EOF > 'disklabel.8'
YX.\" Copyright (c) 1987, 1988, 1991, 1993
YX.\"	The Regents of the University of California.  All rights reserved.
YX.\"
YX.\" This code is derived from software contributed to Berkeley by
YX.\" Symmetric Computer Systems.
YX.\"
YX.\" Redistribution and use in source and binary forms, with or without
YX.\" modification, are permitted provided that the following conditions
YX.\" are met:
YX.\" 1. Redistributions of source code must retain the above copyright
YX.\"    notice, this list of conditions and the following disclaimer.
YX.\" 2. Redistributions in binary form must reproduce the above copyright
YX.\"    notice, this list of conditions and the following disclaimer in the
YX.\"    documentation and/or other materials provided with the distribution.
YX.\" 3. All advertising materials mentioning features or use of this software
YX.\"    must display the following acknowledgement:
YX.\"	This product includes software developed by the University of
YX.\"	California, Berkeley and its contributors.
YX.\" 4. Neither the name of the University nor the names of its contributors
YX.\"    may be used to endorse or promote products derived from this software
YX.\"    without specific prior written permission.
YX.\"
YX.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
YX.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
YX.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
YX.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
YX.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
YX.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
YX.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
YX.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
YX.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
YX.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
YX.\" SUCH DAMAGE.
YX.\"
YX.\"	@(#)disklabel.8	8.2.1 (2.11BSD) 1995/04/21
YX.\"
YX.TH DISKLABEL 8 "April 21, 1995"
YX.UC 2
YX.SH NAME
YXdisklabel \- read and write disk pack label
YX.SH SYNOPSIS
YX.B disklabel \-r
YX.IR disk
YX.br
YX.B disklabel \-w
YX[
YX.B \-r
YX]
YX.IR disk 
YX.IR disktype
YX[
YX.IR packid
YX]
YX.br
YX.B disklabel \-e
YX[
YX.B \-r
YX]
YX.IR disk
YX.br
YX.B disklabel \-R
YX[
YX.B \-r
YX]
YX.IR disk
YX.IR protofile
YX.br
YX.B disklabel
YX[
YX.B \-NW
YX]
YX.IR disk
YX.sp
YX.B disklabel \-B
YX[
YX.B \-b
YX.IR boot
YX]
YX.IR disk
YX[
YX.IR disktype
YX]
YX.br
YX.B disklabel \-w \-B
YX[
YX.B \-b
YX.IR boot
YX]
YX.IR disk
YX.IR disktype
YX[
YX.IR packid
YX]
YX.br
YX.B disklabel \-R \-B
YX[
YX.B \-b
YX.IR boot
YX]
YX.IR disk
YX.IR protofile
YX[
YX.IR disktype
YX]
YX.SH DESCRIPTION
YX.B Disklabel
YXcan be used to install, examine or modify the label on a disk drive or pack.
YXWhen writing the label, it can be used
YXto change the drive identification,
YXthe disk partitions on the drive,
YXor to replace a damaged label.
YXOn some systems,
YX.B disklabel
YXcan be used to install bootstrap code as well.
YXThere are several forms of the command that read (display), install or edit
YXthe label on a disk.
YXEach form has an additional option,
YX\fB\-r\fP,
YXwhich causes the label to be read from or written to the disk directly,
YXrather than going through the system's in-core copy of the label.
YXThis option may allow a label to be installed on a disk
YXwithout kernel support for a label, such as when labels are first installed
YXon a system; it must be used when first installing a label on a disk.
YXThe specific effect of
YX.B \-r
YXis described under each command.
YXThe read and install forms also support the
YX.B \-B
YXoption to install bootstrap code.
YXThese variants are described later.
YX.PP
YXThe first form of the command (read) is used to examine the label on the named
YXdisk drive (e.g. ra0 or /dev/rra0a).
YXIt will display all of the parameters associated with the drive
YXand its partition layout.
YXUnless the
YX.B \-r
YXflag is given,
YXthe kernel's in-core copy of the label is displayed;
YXif the disk has no label, or the partition types on the disk are incorrect,
YXthe kernel may have constructed or modified the label.
YXIf the
YX.B \-r
YXflag is given, the label from the raw disk will be displayed rather
YXthan the in-core label.
YX.PP
YXThe second form of the command, with the
YX.B \-w
YXflag, is used to write a standard label on the designated drive.
YXThe required arguments to
YX.B disklabel
YXare the drive to be labelled (e.g. sd0), and
YXthe drive type as described in the
YX.IR disktab (5)
YXfile.
YXThe drive parameters and partitions are taken from that file.
YXIf different disks of the same physical type are to have different
YXpartitions, it will be necessary to have separate disktab entries
YXdescribing each, or to edit the label after installation as described below.
YXThe optional argument is a pack identification string,
YXup to 16 characters long.
YXThe pack id must be quoted if it contains blanks.
YXIf the
YX.B \-r
YXflag is given, the disk sectors containing the label and bootstrap
YXwill be written directly.
YXA side-effect of this is that any existing bootstrap code will be overwritten
YXand the disk rendered unbootable.
YXIf
YX.B \-r
YXis not specified,
YXthe existing label will be updated via the in-core copy and any bootstrap
YXcode will be unaffected.
YXIf the disk does not already have a label, the
YX.B \-r
YXflag must be used.
YXIn either case, the kernel's in-core label is replaced.
YX.PP
YXAn existing disk label may be edited by using the
YX.B \-e
YXflag.
YXThe label is read from the in-core kernel copy,
YXor directly from the disk if the
YX.B \-r
YXflag is also given.
YXThe label is formatted and then supplied to an editor for changes.
YXIf no editor is specified in an
YX.B EDITOR
YXenvironment variable,
YX.IR vi (1)
YXis used.
YXWhen the editor terminates, the formatted label is reread
YXand used to rewrite the disk label.
YXExisting bootstrap code is unchanged regardless of whether
YX.B \-r
YXwas specified.
YX.PP
YXWith the
YX.B \-R
YXflag,
YX.B disklabel
YXis capable of restoring a disk label that was formatted
YXin a prior operation and saved in an ascii file.
YXThe prototype file used to create the label should be in the same format
YXas that produced when reading or editing a label.
YXComments are delimited by
YX.IR \&#
YXand newline.
YXAs with
YX.B \-w ,
YXany existing bootstrap code will be clobbered if
YX.B \-r
YXis specified and will be unaffected otherwise.
YX.PP
YXThe
YX.B \-NW
YXflags for
YX.B disklabel
YXexplicitly disallow and
YXallow, respectively, writing of the pack label area on the selected disk.
YX.PP
YXThe final three forms of
YX.B disklabel
YXare used to install bootstrap code on machines where the bootstrap is part
YXof the label.
YXThe bootstrap code is comprised of one or two boot programs depending on
YXthe machine.
YXThe
YX.B \-B
YXoption is used to denote that bootstrap code is to be installed.
YXThe
YX.B \-r
YXflag is implied by
YX.B \-B
YXand never needs to be specified.
YXThe name of the boot program(s) to be installed can be selected in a
YXvariety of ways.
YXFirst, the names can be specified explicitly via the
YX.B \-b
YXflag.
YXIf the name is not explicitly given, standard boot blocks will be used.
YXThe boot programs are located in
YX.IR /mdec .
YXThe names of the program is taken from the ``b0'' parameter
YXof the
YX.IR disktab (5)
YXentry for the disk if
YX.I disktype
YXwas given and its disktab entry exists and includes that parameter.
YXOtherwise, the boot program name is derived from the name of the disk.
YXThese name is of the form
YX\fIbasename\fPuboot
YX;
YXfor example,
YX.I /usr/mdec/rauboot
YXif the disk device is
YX.IR ra0 .
YX.PP
YXThe first of the three boot-installation forms is used to install
YXbootstrap code without changing the existing label.
YXIt is essentially a read command with respect to the disk label
YXitself and all options are related to the specification of the boot
YXprogram as described previously.
YXThe final two forms are analogous to the basic write and restore versions
YXexcept that they will install bootstrap code in addition to a new label.
YX.SH FILES
YX/etc/disktab
YX.br
YX/mdec/\fIxx\fPuboot
YX.SH EXAMPLES
YX.in +0.5i
YXdisklabel sd0
YX.br
YX.in -0.5i
YX.PP
YXDisplay the in-core label for ra0 as obtained via
YX.IR /dev/rra0a .
YX.PP
YX.in +0.5i
YXdisklabel \-w \-r /dev/rra0a ra81x foo
YX.br
YX.in -0.5i
YX.PP
YXCreate a label for sd0 based on information for ``ra81x'' found in
YX.IR /etc/disktab .
YXAny existing bootstrap code will be clobbered.
YX.PP
YX.in +0.5i
YXdisklabel -e -r ra0
YX.in -0.5i
YX.PP
YXRead the on-disk label for ra0, edit it and reinstall in-core as well
YXas on-disk.
YXExisting bootstrap code is unaffected.
YX.PP
YX.in +0.5i
YXdisklabel -R ra0 mylabel
YX.br
YX.in -0.5i
YX.PP
YXRestore the on-disk and in-core label for sd0 from information in
YX.IR mylabel .
YXExisting bootstrap code is unaffected.
YX.PP
YX.in +0.5i
YXdisklabel -B ra0
YX.br
YX.in -0.5i
YX.PP
YXInstall a new bootstrap on ra0.
YXThe boot code comes from
YX.IR /mdec/rauboot .
YXOn-disk and in-core labels are unchanged.
YX.PP
YX.in +0.5i
YXdisklabel -w -B /dev/rra0a -b newboot ra81x
YX.br
YX.in -0.5i
YX.PP
YXInstall a new label and bootstrap.
YXThe label is derived from disktab information for ``ra81x'' and
YXinstalled both in-core and on-disk.
YXThe bootstrap code comes from the file
YX.IR /mdec/newboot .
YX.SH SEE ALSO
YXdisktab(5), disklabel(5)
YX.SH DIAGNOSTICS
YXThe kernel device drivers will not allow the size of a disk partition
YXto be decreased or the offset of a partition to be changed while it is open.
YXSome device drivers create a label containing only a single large partition
YXif a disk is unlabeled; thus, the label must be written to the ``a''
YXpartition of the disk while it is open.
YXThis sometimes requires the desired label to be set in two steps,
YXthe first one creating at least one other partition,
YXand the second setting the label on the new partition
YXwhile shrinking the ``a'' partition.
YX.SH BUGS
YXWhen a disk name is given without a full pathname,
YXthe constructed device name uses the ``a'' partition on the tahoe and pdp\-11
YXthe ``c'' partition on all others.
YSHAR_EOF
Yfi
Yif test -f 'disklabel.c'
Ythen
Y	echo shar: "will not over-write existing file 'disklabel.c'"
Yelse
Ysed 's/^X//' << \SHAR_EOF > 'disklabel.c'
YX/*
YX * Copyright (c) 1987, 1993
YX *	The Regents of the University of California.  All rights reserved.
YX *
YX * This code is derived from software contributed to Berkeley by
YX * Symmetric Computer Systems.
YX *
YX * Redistribution and use in source and binary forms, with or without
YX * modification, are permitted provided that the following conditions
YX * are met:
YX * 1. Redistributions of source code must retain the above copyright
YX *    notice, this list of conditions and the following disclaimer.
YX * 2. Redistributions in binary form must reproduce the above copyright
YX *    notice, this list of conditions and the following disclaimer in the
YX *    documentation and/or other materials provided with the distribution.
YX * 3. All advertising materials mentioning features or use of this software
YX *    must display the following acknowledgement:
YX *	This product includes software developed by the University of
YX *	California, Berkeley and its contributors.
YX * 4. Neither the name of the University nor the names of its contributors
YX *    may be used to endorse or promote products derived from this software
YX *    without specific prior written permission.
YX *
YX * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
YX * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
YX * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
YX * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
YX * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
YX * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
YX * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
YX * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
YX * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
YX * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
YX * SUCH DAMAGE.
YX */
YX
YX#if	!defined(lint) && defined(DOSCCS)
YXstatic char copyright[] =
YX"@(#) Copyright (c) 1987, 1993\n\
YX	The Regents of the University of California.  All rights reserved.\n";
YX
YXstatic char sccsid[] = "@(#)disklabel.c	8.1.2 (2.11BSD) 1995/07/10";
YX/* from static char sccsid[] = "@(#)disklabel.c	1.2 (Symmetric) 11/28/85"; */
YX#endif
YX
YX#include <sys/param.h>
YX#include <sys/signal.h>
YX#include <sys/errno.h>
YX#include <sys/file.h>
YX#include <sys/ioctl.h>
YX#include <sys/stat.h>
YX#define DKTYPENAMES
YX#include <sys/disklabel.h>
YX#include <sys/fs.h>
YX#include <string.h>
YX#include <stdio.h>
YX#include <ctype.h>
YX#include "pathnames.h"
YX
YX/*
YX * Disklabel: read and write disklabels.
YX * The label is usually placed on one of the first sectors of the disk.
YX * Many machines also place a bootstrap in the same area,
YX * in which case the label is embedded in the bootstrap.
YX * The bootstrap source must leave space at the proper offset
YX * for the label on such machines.
YX */
YX
YX/*
YX * 2.11BSD has to do some things differently than other systems.  BBSIZE
YX * may be 1024 bytes but the disk boot roms only read the 512 byte sector 0.
YX * The boot and label areas each occupy 1/2 of the 1kb 'filesystem block' 
YX * which precedes the superblock.  The bootblock is sector 0 and the label block
YX * is sector 1.  Each is a disjoint and independent area.  Thus the logic in
YX * this program which treated the label area as a subset or offset of the
YX * boot area had to change.
YX *
YX * The 'a' partition is used to access the raw device - as did the 'tahoe'.
YX*/
YX
YX#define RAWPARTITION	'a'
YX
YX#define	DEFEDITOR	_PATH_VI
YX#define	streq(a,b)	(strcmp(a,b) == 0)
YX
YXchar	*dkname;
YXchar	*specname;
YXchar	tmpfil[] = _PATH_TMP;
YX
YXextern	int errno;
YXextern	long atol();
YX
YXchar	namebuf[256], *np = namebuf;
YXstruct	disklabel lab;
YXstruct	disklabel *readlabel(), *makebootarea();
YXchar	bootarea[BBSIZE];	/* 512 for bootblock, 512 for label */
YX
YXint	installboot;	/* non-zero if we should install a boot program */
YXchar	*xxboot;	/* primary boot */
YXchar	boot0[MAXPATHLEN];
YX
YXenum	{
YX	UNSPEC, EDIT, NOWRITE, READ, RESTORE, WRITE, WRITEABLE, WRITEBOOT
YX} op = UNSPEC;
YX
YXint	rflag;
YX
YX#ifdef DEBUG
YXint	debug;
YX#define OPTIONS	"BNRWb:derw"
YX#else
YX#define OPTIONS	"BNRWb:erw"
YX#endif
YX
YX
YXmain(argc, argv)
YX	int argc;
YX	char *argv[];
YX{
YX	extern char *optarg;
YX	extern int optind;
YX	register struct disklabel *lp;
YX	FILE *t;
YX	int ch, f, flag, error = 0;
YX	char *name = 0;
YX
YX	while ((ch = getopt(argc, argv, OPTIONS)) != EOF)
YX		switch (ch) {
YX			case 'B':
YX				++installboot;
YX				break;
YX			case 'b':
YX				xxboot = optarg;
YX				break;
YX			case 'N':
YX				if (op != UNSPEC)
YX					usage();
YX				op = NOWRITE;
YX				break;
YX			case 'R':
YX				if (op != UNSPEC)
YX					usage();
YX				op = RESTORE;
YX				break;
YX			case 'W':
YX				if (op != UNSPEC)
YX					usage();
YX				op = WRITEABLE;
YX				break;
YX			case 'e':
YX				if (op != UNSPEC)
YX					usage();
YX				op = EDIT;
YX				break;
YX			case 'r':
YX				++rflag;
YX				break;
YX			case 'w':
YX				if (op != UNSPEC)
YX					usage();
YX				op = WRITE;
YX				break;
YX#ifdef DEBUG
YX			case 'd':
YX				debug++;
YX				break;
YX#endif
YX			case '?':
YX			default:
YX				usage();
YX		}
YX	argc -= optind;
YX	argv += optind;
YX	if (installboot) {
YX		rflag++;
YX		if (op == UNSPEC)
YX			op = WRITEBOOT;
YX	} else {
YX		if (op == UNSPEC)
YX			op = READ;
YX		xxboot = 0;
YX	}
YX
YX	if (argc < 1)
YX		usage();
YX
YX	dkname = argv[0];
YX	if (dkname[0] != '/') {
YX		(void)sprintf(np, "%s/r%s%c", _PATH_DEV, dkname, RAWPARTITION);
YX		specname = np;
YX		np += strlen(specname) + 1;
YX	} else
YX		specname = dkname;
YX	f = open(specname, op == READ ? O_RDONLY : O_RDWR);
YX	if (f < 0 && errno == ENOENT && dkname[0] != '/') {
YX		(void)sprintf(specname, "%s/r%s", _PATH_DEV, dkname);
YX		np = namebuf + strlen(specname) + 1;
YX		f = open(specname, op == READ ? O_RDONLY : O_RDWR);
YX	}
YX	if (f < 0)
YX		Perror(specname);
YX
YX	switch(op) {
YX
YX	case EDIT:
YX		if (argc != 1)
YX			usage();
YX		lp = readlabel(f);
YX		error = edit(lp, f);
YX		break;
YX
YX	case NOWRITE:
YX		flag = 0;
YX		if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0)
YX			Perror("ioctl DIOCWLABEL");
YX		break;
YX
YX	case READ:
YX		if (argc != 1)
YX			usage();
YX		lp = readlabel(f);
YX		display(stdout, lp);
YX		error = checklabel(lp);
YX		break;
YX
YX	case RESTORE:
YX		if (installboot && argc == 3) {
YX			makelabel(argv[2], 0, &lab);
YX			argc--;
YX		}
YX		if (argc != 2)
YX			usage();
YX		lp = makebootarea(bootarea, &lab, f);
YX		if (!(t = fopen(argv[1], "r")))
YX			Perror(argv[1]);
YX		if (getasciilabel(t, lp))
YX			error = writelabel(f, bootarea, lp);
YX		break;
YX
YX	case WRITE:
YX		if (argc == 3) {
YX			name = argv[2];
YX			argc--;
YX		}
YX		if (argc != 2)
YX			usage();
YX		makelabel(argv[1], name, &lab);
YX		lp = makebootarea(bootarea, &lab, f);
YX		*lp = lab;
YX		if (checklabel(lp) == 0)
YX			error = writelabel(f, bootarea, lp);
YX		break;
YX
YX	case WRITEABLE:
YX		flag = 1;
YX		if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0)
YX			Perror("ioctl DIOCWLABEL");
YX		break;
YX
YX	case WRITEBOOT:
YX	{
YX		struct disklabel tlab;
YX
YX		lp = readlabel(f);
YX		tlab = *lp;
YX		if (argc == 2)
YX			makelabel(argv[1], 0, &lab);
YX		lp = makebootarea(bootarea, &lab, f);
YX		*lp = tlab;
YX		if (checklabel(lp) == 0)
YX			error = writelabel(f, bootarea, lp);
YX		break;
YX	}
YX	}
YX	exit(error);
YX}
YX
YX/*
YX * Construct a prototype disklabel from /etc/disktab.  As a side
YX * effect, set the names of the primary and secondary boot files
YX * if specified.
YX */
YXmakelabel(type, name, lp)
YX	char *type, *name;
YX	register struct disklabel *lp;
YX{
YX	register struct disklabel *dp;
YX	char *strcpy();
YX
YX	dp = getdiskbyname(type);
YX	if (dp == NULL) {
YX		fprintf(stderr, "%s: unknown disk type\n", type);
YX		exit(1);
YX	}
YX	*lp = *dp;
YX
YX	/*
YX	 * Set bootstrap name.
YX	 * 1. If set from command line, use it,
YX	 * 2. otherwise, check if disktab specifies it (b0),
YX	 * 3. otherwise, makebootarea() will choose one based on the name
YX	 *    of the disk special file. E.g. /dev/ra0 -> rauboot
YX	 */
YX	if (!xxboot && lp->d_boot0) {
YX		if (*lp->d_boot0 != '/')
YX			(void)sprintf(boot0, "%s/%s",
YX				      _PATH_BOOTDIR, lp->d_boot0);
YX		else
YX			(void)strcpy(boot0, lp->d_boot0);
YX		xxboot = boot0;
YX	}
YX	/* d_packname is union d_boot0, so zero */
YX	bzero(lp->d_packname, sizeof(lp->d_packname));
YX	if (name)
YX		(void)strncpy(lp->d_packname, name, sizeof(lp->d_packname));
YX}
YX
YXwritelabel(f, boot, lp)
YX	int f;
YX	char *boot;
YX	register struct disklabel *lp;
YX{
YX	register int i;
YX	int flag;
YX
YX	lp->d_magic = DISKMAGIC;
YX	lp->d_magic2 = DISKMAGIC;
YX	lp->d_checksum = 0;
YX	lp->d_checksum = dkcksum(lp);
YX	if (rflag) {
YX		/*
YX		 * First set the kernel disk label,
YX		 * then write a label to the raw disk.
YX		 * If the SDINFO ioctl fails because it is unimplemented,
YX		 * keep going; otherwise, the kernel consistency checks
YX		 * may prevent us from changing the current (in-core)
YX		 * label.  Normally EFAULT would not be here - but the ioctl
YX		 * maximum data length changed and old kernels would generate
YX		 * an error prematurely in the ioctl dispatch.
YX		 */
YX		if (ioctl(f, DIOCSDINFO, lp) < 0 &&
YX		    errno != EFAULT && errno != ENODEV && errno != ENOTTY) {
YX			l_perror("ioctl DIOCSDINFO");
YX			return (1);
YX		}
YX		(void)lseek(f, (off_t)0, L_SET);
YX		/*
YX		 * write enable label sector before write (if necessary),
YX		 * disable after writing.
YX		 */
YX		flag = 1;
YX		if (ioctl(f, DIOCWLABEL, &flag) < 0)
YX			perror("ioctl DIOCWLABEL");
YX/*
YX * Write the boot block sector (512 bytes) followed immediately by the
YX * label sector (512 bytes) = BBSIZE (1kb) total.
YX*/
YX		if (write(f, boot, BBSIZE) != BBSIZE) {
YX			perror("write");
YX			return (1);
YX		}
YX		flag = 0;
YX		(void) ioctl(f, DIOCWLABEL, &flag);
YX	} else if (ioctl(f, DIOCWDINFO, lp) < 0) {
YX		l_perror("ioctl DIOCWDINFO");
YX		return (1);
YX	}
YX	return (0);
YX}
YX
YXl_perror(s)
YX	char *s;
YX{
YX	int saverrno = errno;
YX
YX	fprintf(stderr, "disklabel: %s: ", s);
YX
YX	switch (saverrno) {
YX
YX	case ESRCH:
YX		fprintf(stderr, "No disk label on disk;\n");
YX		fprintf(stderr,
YX		    "use \"disklabel -r\" to install initial label\n");
YX		break;
YX
YX	case EINVAL:
YX		fprintf(stderr, "Label magic number or checksum is wrong!\n");
YX		fprintf(stderr, "(disklabel or kernel is out of date?)\n");
YX		break;
YX
YX	case EBUSY:
YX		fprintf(stderr, "Open partition would move or shrink\n");
YX		break;
YX
YX	case EXDEV:
YX		fprintf(stderr,
YX	"Labeled partition or 'a' partition must start at beginning of disk\n");
YX		break;
YX
YX	default:
YX		errno = saverrno;
YX		perror((char *)NULL);
YX		break;
YX	}
YX}
YX
YX/*
YX * Fetch disklabel for disk.
YX * Use ioctl to get label unless -r flag is given.
YX *
YX * We use the search logic for the label even though the label will be
YX * in the second half of the bootarea.  If there ever is a valid label
YX * residing in the boot sector things are going to get weird.
YX */
YXstruct disklabel *
YXreadlabel(f)
YX	int f;
YX{
YX	register struct disklabel *lp;
YXregister struct disklabel *xx = (struct disklabel *)(bootarea + BBSIZE - sizeof (struct disklabel));
YX
YX	if (rflag) {
YX		if (lseek(f, (daddr_t)0, L_SET) < 0)
YX			Perror(specname);
YX		if (read(f, bootarea, BBSIZE) < BBSIZE)
YX			Perror(specname);
YX		for (lp = (struct disklabel *)bootarea;
YX		    lp <= xx;
YX		    lp = (struct disklabel *)((char *)lp + 16))
YX			if (lp->d_magic == DISKMAGIC &&
YX			    lp->d_magic2 == DISKMAGIC)
YX				break;
YX		if (lp > xx ||
YX		    lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC ||
YX		    dkcksum(lp) != 0) {
YX			fprintf(stderr,
YX	"Bad pack magic number (label is damaged, or pack is unlabeled)\n");
YX			exit (1);
YX		}
YX	} else {
YX		lp = &lab;
YX		if (ioctl(f, DIOCGDINFO, lp) < 0)
YX			Perror("ioctl DIOCGDINFO");
YX	}
YX	return (lp);
YX}
YX
YX/*
YX * Construct a bootarea (d_bbsize bytes) in the specified buffer ``boot''
YX * Returns a pointer to the disklabel portion of the bootarea.
YX */
YXstruct disklabel *
YXmakebootarea(boot, dp, f)
YX	char *boot;
YX	register struct disklabel *dp;
YX	int f;
YX{
YX	struct disklabel *lp;
YX	register char *p;
YX	int b;
YX	char *dkbasename;
YX	struct stat sb;
YX
YX	/* XXX */
YX	/*
YX	 * sectors are 512 bytes, filesystem blocks are DEV_BSIZE (1024) bytes.
YX	 * We override the sector size so that things like the RL02 work 
YX	 * right.  The RL drives use a hardware sector size of 256 bytes
YX	 * which would wreck havoc in the calculation below.  Actually the
YX	 * disktab file should be "fixed" - all entries should omit 'se' and
YX	 * use the default of 512.
YX	*/
YX	dp->d_secsize = 512;
YX	dp->d_bbsize = 512;
YX	lp = (struct disklabel *)
YX		(boot + (LABELSECTOR * dp->d_secsize) + LABELOFFSET);
YX	bzero((char *)lp, sizeof *lp);
YX
YX	/*
YX	 * If we are not installing a boot program but we are installing a
YX	 * label on disk then we must read the current bootarea so we don't
YX	 * clobber the existing boot.
YX	 */
YX	if (!installboot) {
YX		if (rflag) {
YX			if (lseek(f, (daddr_t)0, L_SET) < 0)
YX				Perror(specname);
YX			if (read(f, boot, BBSIZE) < BBSIZE)
YX				Perror(specname);
YX			bzero((char *)lp, sizeof *lp);
YX		}
YX		return (lp);
YX	}
YX	/*
YX	 * We are installing a boot program.  Determine the name(s) and
YX	 * read them into the appropriate places in the boot area.
YX	 */
YX	if (!xxboot) {
YX		dkbasename = np;
YX		if ((p = rindex(dkname, '/')) == NULL)
YX			p = dkname;
YX		else
YX			p++;
YX		while (*p && !isdigit(*p))
YX			*np++ = *p++;
YX		*np++ = '\0';
YX
YX		(void)sprintf(np, "%s/%suboot",
YX			      _PATH_BOOTDIR, dkbasename);
YX		if (access(np, F_OK) < 0 && dkbasename[0] == 'r')
YX			dkbasename++;
YX		xxboot = np;
YX		(void)sprintf(xxboot, "%s/%suboot",
YX			      _PATH_BOOTDIR, dkbasename);
YX		np += strlen(xxboot) + 1;
YX	}
YX#ifdef DEBUG
YX	if (debug)
YX		fprintf(stderr, "bootstrap: xxboot = %s\n", xxboot);
YX#endif
YX
YX	/*
YX	 * Rule:
YX	 * 1. One-piece bootstrap up to 512 bytes is all that is supported.
YX	 */
YX	b = open(xxboot, O_RDONLY);
YX	if (b < 0)
YX		Perror(xxboot);
YX	if (read(b, boot, 512) < 0)
YX		Perror(xxboot);
YX	(void)fstat(b, &sb);
YX	if (sb.st_size > 512)
YX		Warning("boot > 512 bytes - filesystem likely not bootable");
YX	(void)close(b);
YX	return (lp);
YX}
YX
YXdisplay(f, lp)
YX	FILE *f;
YX	register struct disklabel *lp;
YX{
YX	register int i, j;
YX	register struct partition *pp;
YX
YX	fprintf(f, "# %s:\n", specname);
YX	if ((unsigned) lp->d_type < DKMAXTYPES)
YX		fprintf(f, "type: %s\n", dktypenames[lp->d_type]);
YX	else
YX		fprintf(f, "type: %d\n", lp->d_type);
YX	fprintf(f, "disk: %.*s\n", sizeof(lp->d_typename), lp->d_typename);
YX	fprintf(f, "label: %.*s\n", sizeof(lp->d_packname), lp->d_packname);
YX	fprintf(f, "flags:");
YX	if (lp->d_flags & D_REMOVABLE)
YX		fprintf(f, " removeable");
YX	if (lp->d_flags & D_ECC)
YX		fprintf(f, " ecc");
YX	if (lp->d_flags & D_BADSECT)
YX		fprintf(f, " badsect");
YX	fprintf(f, "\n");
YX	fprintf(f, "bytes/sector: %d\n", lp->d_secsize);
YX	fprintf(f, "sectors/track: %d\n", lp->d_nsectors);
YX	fprintf(f, "tracks/cylinder: %d\n", lp->d_ntracks);
YX	fprintf(f, "sectors/cylinder: %d\n", lp->d_secpercyl);
YX	fprintf(f, "cylinders: %d\n", lp->d_ncylinders);
YX	fprintf(f, "rpm: %d\n", lp->d_rpm);
YX	fprintf(f, "interleave: %d\n", lp->d_interleave);
YX	fprintf(f, "trackskew: %d\n", lp->d_trackskew);
YX	fprintf(f, "cylinderskew: %d\n", lp->d_cylskew);
YX	fprintf(f, "headswitch: %d\t\t# milliseconds\n", lp->d_headswitch);
YX	fprintf(f, "track-to-track seek: %d\t# milliseconds\n", lp->d_trkseek);
YX	fprintf(f, "drivedata: ");
YX	for (i = NDDATA - 1; i >= 0; i--)
YX		if (lp->d_drivedata[i])
YX			break;
YX	if (i < 0)
YX		i = 0;
YX	for (j = 0; j <= i; j++)
YX		fprintf(f, "%ld ", lp->d_drivedata[j]);
YX	fprintf(f, "\n\n%d partitions:\n", lp->d_npartitions);
YX	fprintf(f,
YX	    "#        size   offset    fstype   [fsize bsize]\n");
YX	pp = lp->d_partitions;
YX	for (i = 0; i < lp->d_npartitions; i++, pp++) {
YX		if (pp->p_size) {
YX			fprintf(f, "  %c: %8ld %8ld  ", 'a' + i,
YX			   pp->p_size, pp->p_offset);
YX			if ((unsigned) pp->p_fstype < FSMAXTYPES)
YX				fprintf(f, "%8.8s", fstypenames[pp->p_fstype]);
YX			else
YX				fprintf(f, "%8d", pp->p_fstype);
YX			switch (pp->p_fstype) {
YX
YX			case FS_V71K:
YX			case FS_UNUSED:				/* XXX */
YX				fprintf(f, "    %5d %5d ",
YX				    pp->p_fsize, pp->p_fsize * pp->p_frag);
YX				break;
YX
YX			default:
YX				fprintf(f, "%20.20s", "");
YX				break;
YX			}
YX			fprintf(f, "\t# (Cyl. %4ld",
YX			    pp->p_offset / lp->d_secpercyl);
YX			if (pp->p_offset % lp->d_secpercyl)
YX			    putc('*', f);
YX			else
YX			    putc(' ', f);
YX			fprintf(f, "- %ld",
YX			    (pp->p_offset + 
YX			    pp->p_size + lp->d_secpercyl - 1) /
YX			    lp->d_secpercyl - 1);
YX			if (pp->p_size % lp->d_secpercyl)
YX			    putc('*', f);
YX			fprintf(f, ")\n");
YX		}
YX	}
YX	fflush(f);
YX}
YX
YXedit(lp, f)
YX	struct disklabel *lp;
YX	int f;
YX{
YX	register int c;
YX	struct disklabel label;
YX	FILE *fd;
YX	char *mktemp();
YX
YX	(void) mktemp(tmpfil);
YX	fd = fopen(tmpfil, "w");
YX	if (fd == NULL) {
YX		fprintf(stderr, "%s: Can't create\n", tmpfil);
YX		return (1);
YX	}
YX	(void)fchmod(fileno(fd), 0600);
YX	display(fd, lp);
YX	fclose(fd);
YX	for (;;) {
YX		if (!editit())
YX			break;
YX		fd = fopen(tmpfil, "r");
YX		if (fd == NULL) {
YX			fprintf(stderr, "%s: Can't reopen for reading\n",
YX				tmpfil);
YX			break;
YX		}
YX		bzero((char *)&label, sizeof(label));
YX		if (getasciilabel(fd, &label)) {
YX			*lp = label;
YX			if (writelabel(f, bootarea, lp) == 0) {
YX				(void) unlink(tmpfil);
YX				return (0);
YX			}
YX		}
YX		printf("re-edit the label? [y]: "); fflush(stdout);
YX		c = getchar();
YX		if (c != EOF && c != (int)'\n')
YX			while (getchar() != (int)'\n')
YX				;
YX		if  (c == (int)'n')
YX			break;
YX	}
YX	(void) unlink(tmpfil);
YX	return (1);
YX}
YX
YXeditit()
YX{
YX	register int pid, xpid;
YX	int stat;
YX	long omask;
YX	extern char *getenv();
YX
YX	omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
YX	while ((pid = fork()) < 0) {
YX		extern int errno;
YX
YX		if (errno == EPROCLIM) {
YX			fprintf(stderr, "You have too many processes\n");
YX			return(0);
YX		}
YX		if (errno != EAGAIN) {
YX			perror("fork");
YX			return(0);
YX		}
YX		sleep(1);
YX	}
YX	if (pid == 0) {
YX		register char *ed;
YX
YX		sigsetmask(omask);
YX		setgid(getgid());
YX		setuid(getuid());
YX		if ((ed = getenv("EDITOR")) == (char *)0)
YX			ed = DEFEDITOR;
YX		execlp(ed, ed, tmpfil, 0);
YX		perror(ed);
YX		exit(1);
YX	}
YX	while ((xpid = wait(&stat)) >= 0)
YX		if (xpid == pid)
YX			break;
YX	sigsetmask(omask);
YX	return(!stat);
YX}
YX
YXchar *
YXskip(cp)
YX	register char *cp;
YX{
YX
YX	while (*cp != '\0' && isspace(*cp))
YX		cp++;
YX	if (*cp == '\0' || *cp == '#')
YX		return ((char *)NULL);
YX	return (cp);
YX}
YX
YXchar *
YXword(cp)
YX	register char *cp;
YX{
YX	register char c;
YX
YX	while (*cp != '\0' && !isspace(*cp) && *cp != '#')
YX		cp++;
YX	if ((c = *cp) != '\0') {
YX		*cp++ = '\0';
YX		if (c != '#')
YX			return (skip(cp));
YX	}
YX	return ((char *)NULL);
YX}
YX
YX/*
YX * Read an ascii label in from fd f,
YX * in the same format as that put out by display(),
YX * and fill in lp.
YX */
YXgetasciilabel(f, lp)
YX	FILE	*f;
YX	register struct disklabel *lp;
YX{
YX	register char **cpp, *cp;
YX	register struct partition *pp;
YX	char *tp, *s, line[BUFSIZ];
YX	int lineno = 0, errors = 0;
YX	long v;
YX
YX	lp->d_bbsize = 512;				/* XXX */
YX	lp->d_sbsize = SBSIZE;
YX	while (fgets(line, sizeof(line) - 1, f)) {
YX		lineno++;
YX		if (cp = index(line,'\n'))
YX			*cp = '\0';
YX		cp = skip(line);
YX		if (cp == NULL)
YX			continue;
YX		tp = index(cp, ':');
YX		if (tp == NULL) {
YX			fprintf(stderr, "line %d: syntax error\n", lineno);
YX			errors++;
YX			continue;
YX		}
YX		*tp++ = '\0', tp = skip(tp);
YX		if (streq(cp, "type")) {
YX			if (tp == NULL)
YX				tp = "unknown";
YX			cpp = dktypenames;
YX			for (; cpp < &dktypenames[DKMAXTYPES]; cpp++)
YX				if ((s = *cpp) && streq(s, tp)) {
YX					lp->d_type = cpp - dktypenames;
YX					goto next;
YX				}
YX			v = atoi(tp);
YX			if ((unsigned)v >= DKMAXTYPES)
YX				fprintf(stderr, "line %d:%s %d\n", lineno,
YX				    "Warning, unknown disk type", v);
YX			lp->d_type = v;
YX			continue;
YX		}
YX		if (streq(cp, "flags")) {
YX			for (v = 0; (cp = tp) && *cp != '\0';) {
YX				tp = word(cp);
YX				if (streq(cp, "removeable"))
YX					v |= D_REMOVABLE;
YX				else if (streq(cp, "ecc"))
YX					v |= D_ECC;
YX				else if (streq(cp, "badsect"))
YX					v |= D_BADSECT;
YX				else {
YX					fprintf(stderr,
YX					    "line %d: %s: bad flag\n",
YX					    lineno, cp);
YX					errors++;
YX				}
YX			}
YX			lp->d_flags = v;
YX			continue;
YX		}
YX		if (streq(cp, "drivedata")) {
YX			register int i;
YX
YX			for (i = 0; (cp = tp) && *cp != '\0' && i < NDDATA;) {
YX				lp->d_drivedata[i++] = atol(cp);
YX				tp = word(cp);
YX			}
YX			continue;
YX		}
YX		if (sscanf(cp, "%ld partitions", &v) == 1) {
YX			if (v == 0 || (unsigned)v > MAXPARTITIONS) {
YX				fprintf(stderr,
YX				    "line %d: bad # of partitions\n", lineno);
YX				lp->d_npartitions = MAXPARTITIONS;
YX				errors++;
YX			} else
YX				lp->d_npartitions = v;
YX			continue;
YX		}
YX		if (tp == NULL)
YX			tp = "";
YX		if (streq(cp, "disk")) {
YX			strncpy(lp->d_typename, tp, sizeof (lp->d_typename));
YX			continue;
YX		}
YX		if (streq(cp, "label")) {
YX			strncpy(lp->d_packname, tp, sizeof (lp->d_packname));
YX			continue;
YX		}
YX/*
YX * ARGH!  Have to fix the 'se#256' entries in disktab after all or this
YX * check will cause errors.
YX*/
YX		if (streq(cp, "bytes/sector")) {
YX			v = atoi(tp);
YX			if (v <= 0 || (v % 512) != 0) {
YX				fprintf(stderr,
YX				    "line %d: %s: bad sector size\n",
YX				    lineno, tp);
YX				errors++;
YX			} else
YX				lp->d_secsize = v;
YX			continue;
YX		}
YX		if (streq(cp, "sectors/track")) {
YX			v = atoi(tp);
YX			if (v <= 0) {
YX				fprintf(stderr, "line %d: %s: bad %s\n",
YX				    lineno, tp, cp);
YX				errors++;
YX			} else
YX				lp->d_nsectors = v;
YX			continue;
YX		}
YX		if (streq(cp, "sectors/cylinder")) {
YX			v = atoi(tp);
YX			if (v <= 0) {
YX				fprintf(stderr, "line %d: %s: bad %s\n",
YX				    lineno, tp, cp);
YX				errors++;
YX			} else
YX				lp->d_secpercyl = v;
YX			continue;
YX		}
YX		if (streq(cp, "tracks/cylinder")) {
YX			v = atoi(tp);
YX			if (v <= 0) {
YX				fprintf(stderr, "line %d: %s: bad %s\n",
YX				    lineno, tp, cp);
YX				errors++;
YX			} else
YX				lp->d_ntracks = v;
YX			continue;
YX		}
YX		if (streq(cp, "cylinders")) {
YX			v = atoi(tp);
YX			if (v <= 0) {
YX				fprintf(stderr, "line %d: %s: bad %s\n",
YX				    lineno, tp, cp);
YX				errors++;
YX			} else
YX				lp->d_ncylinders = v;
YX			continue;
YX		}
YX		if (streq(cp, "rpm")) {
YX			v = atoi(tp);
YX			if (v <= 0) {
YX				fprintf(stderr, "line %d: %s: bad %s\n",
YX				    lineno, tp, cp);
YX				errors++;
YX			} else
YX				lp->d_rpm = v;
YX			continue;
YX		}
YX		if (streq(cp, "interleave")) {
YX			v = atoi(tp);
YX			if (v <= 0) {
YX				fprintf(stderr, "line %d: %s: bad %s\n",
YX				    lineno, tp, cp);
YX				errors++;
YX			} else
YX				lp->d_interleave = v;
YX			continue;
YX		}
YX		if (streq(cp, "trackskew")) {
YX			v = atoi(tp);
YX			if (v < 0) {
YX				fprintf(stderr, "line %d: %s: bad %s\n",
YX				    lineno, tp, cp);
YX				errors++;
YX			} else
YX				lp->d_trackskew = v;
YX			continue;
YX		}
YX		if (streq(cp, "cylinderskew")) {
YX			v = atoi(tp);
YX			if (v < 0) {
YX				fprintf(stderr, "line %d: %s: bad %s\n",
YX				    lineno, tp, cp);
YX				errors++;
YX			} else
YX				lp->d_cylskew = v;
YX			continue;
YX		}
YX		if (streq(cp, "headswitch")) {
YX			v = atoi(tp);
YX			if (v < 0) {
YX				fprintf(stderr, "line %d: %s: bad %s\n",
YX				    lineno, tp, cp);
YX				errors++;
YX			} else
YX				lp->d_headswitch = v;
YX			continue;
YX		}
YX		if (streq(cp, "track-to-track seek")) {
YX			v = atoi(tp);
YX			if (v < 0) {
YX				fprintf(stderr, "line %d: %s: bad %s\n",
YX				    lineno, tp, cp);
YX				errors++;
YX			} else
YX				lp->d_trkseek = v;
YX			continue;
YX		}
YX		if ('a' <= *cp && *cp <= 'z' && cp[1] == '\0') {
YX			unsigned part = *cp - 'a';
YX
YX			if (part > lp->d_npartitions) {
YX				fprintf(stderr,
YX				    "line %d: bad partition name '%c' %d %d\n",
YX					lineno, *cp, part, lp->d_npartitions);
YX				errors++;
YX				continue;
YX			}
YX			pp = &lp->d_partitions[part];
YX#define NXTNUM(n) { \
YX	cp = tp, tp = word(cp); \
YX	if (tp == NULL) \
YX		tp = cp; \
YX	(n) = atol(cp); \
YX     }
YX
YX			NXTNUM(v);
YX			if (v < 0) {
YX				fprintf(stderr,
YX				    "line %d: %s: bad partition size\n",
YX				    lineno, cp);
YX				errors++;
YX			} else
YX				pp->p_size = v;
YX			NXTNUM(v);
YX			if (v < 0) {
YX				fprintf(stderr,
YX				    "line %d: %s: bad partition offset\n",
YX				    lineno, cp);
YX				errors++;
YX			} else
YX				pp->p_offset = v;
YX			cp = tp, tp = word(cp);
YX			cpp = fstypenames;
YX			for (; cpp < &fstypenames[FSMAXTYPES]; cpp++)
YX				if ((s = *cpp) && streq(s, cp)) {
YX					pp->p_fstype = cpp - fstypenames;
YX					goto gottype;
YX				}
YX			if (isdigit(*cp))
YX				v = atoi(cp);
YX			else
YX				v = FSMAXTYPES;
YX			if ((unsigned)v >= FSMAXTYPES) {
YX				fprintf(stderr, "line %d: %s %s\n", lineno,
YX				    "Warning, unknown filesystem type", cp);
YX				v = FS_UNUSED;
YX			}
YX			pp->p_fstype = v;
YX	gottype:
YX
YX			switch (pp->p_fstype) {
YX
YX			case FS_UNUSED:				/* XXX */
YX			case FS_V71K:
YX				NXTNUM(pp->p_fsize);
YX				if (pp->p_fsize == 0)
YX					break;
YX				NXTNUM(v);
YX				pp->p_frag = v / pp->p_fsize;
YX				break;
YX
YX			default:
YX				break;
YX			}
YX			continue;
YX		}
YX		fprintf(stderr, "line %d: %s: Unknown disklabel field\n",
YX		    lineno, cp);
YX		errors++;
YX	next:
YX		;
YX	}
YX	errors += checklabel(lp);
YX	return (errors == 0);
YX}
YX
YX/*
YX * Check disklabel for errors and fill in
YX * derived fields according to supplied values.
YX */
YXchecklabel(lp)
YX	register struct disklabel *lp;
YX{
YX	register struct partition *pp;
YX	int i, errors = 0;
YX	char part;
YX
YX	if (lp->d_secsize == 0) {
YX		fprintf(stderr, "sector size %d\n", lp->d_secsize);
YX		return (1);
YX	}
YX	if (lp->d_nsectors == 0) {
YX		fprintf(stderr, "sectors/track %d\n", lp->d_nsectors);
YX		return (1);
YX	}
YX	if (lp->d_ntracks == 0) {
YX		fprintf(stderr, "tracks/cylinder %d\n", lp->d_ntracks);
YX		return (1);
YX	}
YX	if  (lp->d_ncylinders == 0) {
YX		fprintf(stderr, "cylinders/unit %d\n", lp->d_ncylinders);
YX		errors++;
YX	}
YX	if (lp->d_rpm == 0)
YX		Warning("revolutions/minute %d", lp->d_rpm);
YX	if (lp->d_secpercyl == 0)
YX		lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
YX	if (lp->d_secperunit == 0)
YX		lp->d_secperunit = (long) lp->d_secpercyl * lp->d_ncylinders;
YX	if (lp->d_bbsize == 0) {
YX		fprintf(stderr, "boot block size %d\n", lp->d_bbsize);
YX		errors++;
YX	} else if (lp->d_bbsize % lp->d_secsize)
YX		Warning("boot block size %% sector-size != 0");
YX	if (lp->d_sbsize == 0) {
YX		fprintf(stderr, "super block size %d\n", lp->d_sbsize);
YX		errors++;
YX	} else if (lp->d_sbsize % lp->d_secsize)
YX		Warning("super block size %% sector-size != 0");
YX	if (lp->d_npartitions > MAXPARTITIONS)
YX		Warning("number of partitions (%d) > MAXPARTITIONS (%d)",
YX		    lp->d_npartitions, MAXPARTITIONS);
YX	for (i = 0; i < lp->d_npartitions; i++) {
YX		part = 'a' + i;
YX		pp = &lp->d_partitions[i];
YX		if (pp->p_size == 0 && pp->p_offset != 0)
YX			Warning("partition %c: size 0, but offset %ld",
YX			    part, pp->p_offset);
YX#ifdef notdef
YX		if (pp->p_size % lp->d_secpercyl)
YX			Warning("partition %c: size %% cylinder-size != 0",
YX			    part);
YX		if (pp->p_offset % lp->d_secpercyl)
YX			Warning("partition %c: offset %% cylinder-size != 0",
YX			    part);
YX#endif
YX		if (pp->p_offset > lp->d_secperunit) {
YX			fprintf(stderr,
YX			    "partition %c: offset past end of unit %ld %ld\n",
YX				part, pp->p_offset, lp->d_secperunit);
YX			errors++;
YX		}
YX		if (pp->p_offset + pp->p_size > lp->d_secperunit) {
YX			fprintf(stderr,
YX			    "partition %c: extends past end of unit %ld %ld %ld\n",
YX			    part, pp->p_offset, pp->p_size, lp->d_secperunit);
YX			errors++;
YX		}
YX	}
YX	for (; i < MAXPARTITIONS; i++) {
YX		part = 'a' + i;
YX		pp = &lp->d_partitions[i];
YX		if (pp->p_size || pp->p_offset)
YX			Warning("unused partition %c: size %ld offset %ld",
YX			    'a' + i, pp->p_size, pp->p_offset);
YX	}
YX	return (errors);
YX}
YX
YX/*VARARGS1*/
YXWarning(fmt, a1, a2, a3, a4, a5)
YX	char *fmt;
YX{
YX
YX	fprintf(stderr, "Warning, ");
YX	fprintf(stderr, fmt, a1, a2, a3, a4, a5);
YX	fprintf(stderr, "\n");
YX}
YX
YXPerror(str)
YX	char *str;
YX{
YX	fputs("disklabel: ", stderr); perror(str);
YX	exit(4);
YX}
YX
YXusage()
YX{
YX	fprintf(stderr,
YX"%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",
YX"usage: disklabel [-r] disk",
YX		"(to read label)",
YX"or disklabel -w [-r] disk type [ packid ]",
YX		"(to write label with existing boot program)",
YX"or disklabel -e [-r] disk",
YX		"(to edit label)",
YX"or disklabel -R [-r] disk protofile",
YX		"(to restore label with existing boot program)",
YX"or disklabel -B [ -b bootprog ] disk [ type ]",
YX		"(to install boot program with existing on-disk label)",
YX"or disklabel -w -B [ -b bootprog ] disk type [ packid ]",
YX		"(to write label and install boot program)",
YX"or disklabel -R -B [ -b bootprog ] disk protofile [ type ]",
YX		"(to restore label and install boot program)",
YX"or disklabel [-NW] disk",
YX		"(to write disable/enable label)");
YX	exit(1);
YX}
YSHAR_EOF
Yfi
Yif test -f 'pathnames.h'
Ythen
Y	echo shar: "will not over-write existing file 'pathnames.h'"
Yelse
Ysed 's/^X//' << \SHAR_EOF > 'pathnames.h'
YX/*
YX * Copyright (c) 1989, 1993
YX *	The Regents of the University of California.  All rights reserved.
YX *
YX * Redistribution and use in source and binary forms, with or without
YX * modification, are permitted provided that the following conditions
YX * are met:
YX * 1. Redistributions of source code must retain the above copyright
YX *    notice, this list of conditions and the following disclaimer.
YX * 2. Redistributions in binary form must reproduce the above copyright
YX *    notice, this list of conditions and the following disclaimer in the
YX *    documentation and/or other materials provided with the distribution.
YX * 3. All advertising materials mentioning features or use of this software
YX *    must display the following acknowledgement:
YX *	This product includes software developed by the University of
YX *	California, Berkeley and its contributors.
YX * 4. Neither the name of the University nor the names of its contributors
YX *    may be used to endorse or promote products derived from this software
YX *    without specific prior written permission.
YX *
YX * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
YX * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
YX * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
YX * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
YX * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
YX * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
YX * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
YX * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
YX * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
YX * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
YX * SUCH DAMAGE.
YX *
YX *	@(#)pathnames.h	8.1.1 (2.11BSD) 4/10/95
YX */
YX
YX#include <paths.h>
YX
YX#define	_PATH_BOOTDIR	"/mdec"
YX#undef _PATH_TMP
YX#define	_PATH_TMP	"/tmp/EdDk.aXXXXXX"
YSHAR_EOF
Yfi
Ycd ..
Yexit 0
Y#	End of shell archive
SHAR_EOF
fi
exit 0
#	End of shell archive
