From d038e02fd667ab6c02875840105798aaa7029504 Mon Sep 17 00:00:00 2001 From: rgrimes Date: Thu, 26 May 1994 06:35:07 +0000 Subject: BSD 4.4 Lite sbin Sources Note: XNSrouted and routed NOT imported here, they shall be imported with usr.sbin. --- sbin/disklabel/Makefile | 14 + sbin/disklabel/disklabel.5.5 | 384 ++++++++++++ sbin/disklabel/disklabel.8 | 343 +++++++++++ sbin/disklabel/disklabel.c | 1314 ++++++++++++++++++++++++++++++++++++++++++ sbin/disklabel/dkcksum.c | 53 ++ sbin/disklabel/pathnames.h | 40 ++ 6 files changed, 2148 insertions(+) create mode 100644 sbin/disklabel/Makefile create mode 100644 sbin/disklabel/disklabel.5.5 create mode 100644 sbin/disklabel/disklabel.8 create mode 100644 sbin/disklabel/disklabel.c create mode 100644 sbin/disklabel/dkcksum.c create mode 100644 sbin/disklabel/pathnames.h (limited to 'sbin/disklabel') diff --git a/sbin/disklabel/Makefile b/sbin/disklabel/Makefile new file mode 100644 index 0000000..3f4749c --- /dev/null +++ b/sbin/disklabel/Makefile @@ -0,0 +1,14 @@ +# @(#)Makefile 8.2 (Berkeley) 3/17/94 + +PROG= disklabel +SRCS= disklabel.c dkcksum.c +MAN8= disklabel.0 +CLEANFILES=disklabel.5.0 + +all: ${PROG} disklabel.5.0 ${MAN8} + +beforeinstall: + install -c -o ${MANOWN} -g ${MANGRP} -m ${MANMODE} disklabel.5.0 \ + ${DESTDIR}${MANDIR}5/disklabel.0 + +.include diff --git a/sbin/disklabel/disklabel.5.5 b/sbin/disklabel/disklabel.5.5 new file mode 100644 index 0000000..fb6f6cd --- /dev/null +++ b/sbin/disklabel/disklabel.5.5 @@ -0,0 +1,384 @@ +.\" 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 +.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. + */ +#if defined(KERNEL) || defined(STANDALONE) + char d_packname[16]; /* pack identifier */ +#else + 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 +#endif /* ! KERNEL or STANDALONE */ + + /* 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 0000000..bf14e0f --- /dev/null +++ b/sbin/disklabel/disklabel.8 @@ -0,0 +1,343 @@ +.\" 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 0000000..4a29340 --- /dev/null +++ b/sbin/disklabel/disklabel.c @@ -0,0 +1,1314 @@ +/* + * 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 +static char sccsid[] = "@(#)disklabel.c 8.2 (Berkeley) 1/7/94"; +/* from static char sccsid[] = "@(#)disklabel.c 1.2 (Symmetric) 11/28/85"; */ +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#define DKTYPENAMES +#include +#include +#include +#include +#include +#include +#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. + */ + +#ifdef tahoe +#define RAWPARTITION 'a' +#else +#define RAWPARTITION 'c' +#endif + +#ifndef BBSIZE +#define BBSIZE 8192 /* size of boot area, with label */ +#endif + +#ifdef tahoe +#define NUMBOOT 0 +#else +#if defined(hp300) || defined(hp800) +#define NUMBOOT 1 +#else +#define NUMBOOT 2 +#endif +#endif + +#define DEFEDITOR _PATH_VI +#define streq(a,b) (strcmp(a,b) == 0) + +char *dkname; +char *specname; +char tmpfil[] = _PATH_TMP; + +extern int errno; +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, NOWRITE, READ, RESTORE, WRITE, WRITEABLE, WRITEBOOT +} op = UNSPEC; + +int rflag; + +#ifdef DEBUG +int debug; +#define OPTIONS "BNRWb:ders:w" +#else +#define OPTIONS "BNRWb:ers:w" +#endif + + +main(argc, argv) + int argc; + char *argv[]; +{ + extern char *optarg; + extern int optind; + register struct disklabel *lp; + FILE *t; + int ch, f, flag, error = 0; + char *name = 0; + + while ((ch = getopt(argc, argv, OPTIONS)) != EOF) + 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(); + op = NOWRITE; + break; + case 'R': + if (op != UNSPEC) + usage(); + op = RESTORE; + break; + case 'W': + if (op != UNSPEC) + usage(); + op = WRITEABLE; + 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; + xxboot = bootxx = 0; + } +#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) + Perror(specname); + + switch(op) { + + case EDIT: + if (argc != 1) + usage(); + lp = readlabel(f); + error = edit(lp, f); + break; + + case NOWRITE: + flag = 0; + if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0) + Perror("ioctl DIOCWLABEL"); + break; + + case READ: + if (argc != 1) + usage(); + lp = readlabel(f); + display(stdout, lp); + error = checklabel(lp); + break; + + case RESTORE: +#if NUMBOOT > 0 + if (installboot && argc == 3) { + makelabel(argv[2], 0, &lab); + argc--; + } +#endif + if (argc != 2) + usage(); + lp = makebootarea(bootarea, &lab, f); + if (!(t = fopen(argv[1], "r"))) + Perror(argv[1]); + if (getasciilabel(t, lp)) + error = writelabel(f, bootarea, lp); + break; + + case WRITE: + if (argc == 3) { + name = argv[2]; + argc--; + } + if (argc != 2) + usage(); + makelabel(argv[1], name, &lab); + lp = makebootarea(bootarea, &lab, f); + *lp = lab; + if (checklabel(lp) == 0) + error = writelabel(f, bootarea, lp); + break; + + case WRITEABLE: + flag = 1; + if (ioctl(f, DIOCWLABEL, (char *)&flag) < 0) + Perror("ioctl DIOCWLABEL"); + break; + +#if NUMBOOT > 0 + case WRITEBOOT: + { + struct disklabel tlab; + + lp = readlabel(f); + tlab = *lp; + if (argc == 2) + makelabel(argv[1], 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. + */ +makelabel(type, name, lp) + char *type, *name; + register struct disklabel *lp; +{ + register struct disklabel *dp; + char *strcpy(); + + dp = getdiskbyname(type); + if (dp == NULL) { + fprintf(stderr, "%s: unknown disk type\n", type); + exit(1); + } + *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 */ + bzero(lp->d_packname, sizeof(lp->d_packname)); + if (name) + (void)strncpy(lp->d_packname, name, sizeof(lp->d_packname)); +} + +writelabel(f, boot, lp) + int f; + char *boot; + register struct disklabel *lp; +{ + register int i; + int flag; + + setbootflag(lp); + lp->d_magic = DISKMAGIC; + lp->d_magic2 = DISKMAGIC; + lp->d_checksum = 0; + lp->d_checksum = dkcksum(lp); + if (rflag) { + /* + * 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); + } + (void)lseek(f, (off_t)0, SEEK_SET); + /* + * write enable label sector before write (if necessary), + * disable after writing. + */ + flag = 1; + if (ioctl(f, DIOCWLABEL, &flag) < 0) + perror("ioctl DIOCWLABEL"); + 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 + flag = 0; + (void) ioctl(f, DIOCWLABEL, &flag); + } 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; + + 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) { + int oerrno = errno; + fprintf(stderr, "alternate label %d ", i/2); + errno = oerrno; + perror("write"); + } + } + } +#endif + return (0); +} + +l_perror(s) + char *s; +{ + int saverrno = errno; + + fprintf(stderr, "disklabel: %s: ", s); + + switch (saverrno) { + + case ESRCH: + fprintf(stderr, "No disk label on disk;\n"); + fprintf(stderr, + "use \"disklabel -r\" to install initial label\n"); + break; + + case EINVAL: + fprintf(stderr, "Label magic number or checksum is wrong!\n"); + fprintf(stderr, "(disklabel or kernel is out of date?)\n"); + break; + + case EBUSY: + fprintf(stderr, "Open partition would move or shrink\n"); + break; + + case EXDEV: + fprintf(stderr, + "Labeled partition or 'a' partition must start at beginning of disk\n"); + break; + + default: + errno = saverrno; + perror((char *)NULL); + break; + } +} + +/* + * Fetch disklabel for disk. + * Use ioctl to get label unless -r flag is given. + */ +struct disklabel * +readlabel(f) + int f; +{ + register struct disklabel *lp; + + if (rflag) { + if (read(f, bootarea, BBSIZE) < BBSIZE) + Perror(specname); + for (lp = (struct disklabel *)bootarea; + lp <= (struct disklabel *)(bootarea + BBSIZE - sizeof(*lp)); + lp = (struct disklabel *)((char *)lp + 16)) + if (lp->d_magic == DISKMAGIC && + lp->d_magic2 == DISKMAGIC) + break; + if (lp > (struct disklabel *)(bootarea+BBSIZE-sizeof(*lp)) || + lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC || + dkcksum(lp) != 0) { + fprintf(stderr, + "Bad pack magic number (label is damaged, or pack is unlabeled)\n"); + /* lp = (struct disklabel *)(bootarea + LABELOFFSET); */ + exit (1); + } + } else { + lp = &lab; + if (ioctl(f, DIOCGDINFO, lp) < 0) + Perror("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; + register struct disklabel *dp; + int f; +{ + struct disklabel *lp; + register 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); + bzero((char *)lp, 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) + Perror(specname); + bzero((char *)lp, 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 = rindex(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) + fprintf(stderr, "bootstraps: xxboot = %s, bootxx = %s\n", + 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) + Perror(xxboot); +#if NUMBOOT > 1 + if (read(b, boot, (int)dp->d_secsize) < 0) + Perror(xxboot); + (void)close(b); + b = open(bootxx, O_RDONLY); + if (b < 0) + Perror(bootxx); + if (read(b, &boot[dp->d_secsize], (int)(dp->d_bbsize-dp->d_secsize)) < 0) + Perror(bootxx); +#else + if (read(b, boot, (int)dp->d_bbsize) < 0) + Perror(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) + Perror(xxboot); + if (read(b, bootbuf, bootsize) < 0) { + free(bootbuf); + Perror(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) { + fprintf(stderr, + "Bootstrap doesn't leave room for disk label\n"); + exit(2); + } + return (lp); +} + +display(f, lp) + FILE *f; + register struct disklabel *lp; +{ + register int i, j; + register 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, " removeable"); + 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); +} + +edit(lp, f) + struct disklabel *lp; + int f; +{ + register int c; + struct disklabel label; + FILE *fd; + char *mktemp(); + + (void) mktemp(tmpfil); + fd = fopen(tmpfil, "w"); + if (fd == NULL) { + fprintf(stderr, "%s: Can't create\n", tmpfil); + return (1); + } + (void)fchmod(fileno(fd), 0600); + display(fd, lp); + fclose(fd); + for (;;) { + if (!editit()) + break; + fd = fopen(tmpfil, "r"); + if (fd == NULL) { + fprintf(stderr, "%s: Can't reopen for reading\n", + tmpfil); + break; + } + bzero((char *)&label, 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); + c = getchar(); + if (c != EOF && c != (int)'\n') + while (getchar() != (int)'\n') + ; + if (c == (int)'n') + break; + } + (void) unlink(tmpfil); + return (1); +} + +editit() +{ + register int pid, xpid; + int stat, omask; + extern char *getenv(); + + omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); + while ((pid = fork()) < 0) { + extern int errno; + + if (errno == EPROCLIM) { + fprintf(stderr, "You have too many processes\n"); + return(0); + } + if (errno != EAGAIN) { + perror("fork"); + return(0); + } + sleep(1); + } + if (pid == 0) { + register char *ed; + + sigsetmask(omask); + 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; + sigsetmask(omask); + return(!stat); +} + +char * +skip(cp) + register char *cp; +{ + + while (*cp != '\0' && isspace(*cp)) + cp++; + if (*cp == '\0' || *cp == '#') + return ((char *)NULL); + return (cp); +} + +char * +word(cp) + register char *cp; +{ + register char c; + + while (*cp != '\0' && !isspace(*cp) && *cp != '#') + cp++; + if ((c = *cp) != '\0') { + *cp++ = '\0'; + if (c != '#') + return (skip(cp)); + } + return ((char *)NULL); +} + +/* + * Read an ascii label in from fd f, + * in the same format as that put out by display(), + * and fill in lp. + */ +getasciilabel(f, lp) + FILE *f; + register struct disklabel *lp; +{ + register char **cpp, *cp; + register 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 = index(line,'\n')) + *cp = '\0'; + cp = skip(line); + if (cp == NULL) + continue; + tp = index(cp, ':'); + if (tp == NULL) { + fprintf(stderr, "line %d: syntax error\n", lineno); + errors++; + continue; + } + *tp++ = '\0', tp = skip(tp); + if (streq(cp, "type")) { + if (tp == NULL) + tp = "unknown"; + cpp = dktypenames; + for (; cpp < &dktypenames[DKMAXTYPES]; cpp++) + if ((s = *cpp) && streq(s, tp)) { + lp->d_type = cpp - dktypenames; + goto next; + } + v = atoi(tp); + if ((unsigned)v >= DKMAXTYPES) + fprintf(stderr, "line %d:%s %d\n", lineno, + "Warning, unknown disk type", v); + lp->d_type = v; + continue; + } + if (streq(cp, "flags")) { + for (v = 0; (cp = tp) && *cp != '\0';) { + tp = word(cp); + if (streq(cp, "removeable")) + v |= D_REMOVABLE; + else if (streq(cp, "ecc")) + v |= D_ECC; + else if (streq(cp, "badsect")) + v |= D_BADSECT; + else { + fprintf(stderr, + "line %d: %s: bad flag\n", + lineno, cp); + errors++; + } + } + lp->d_flags = v; + continue; + } + if (streq(cp, "drivedata")) { + register 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) { + fprintf(stderr, + "line %d: bad # of partitions\n", lineno); + lp->d_npartitions = MAXPARTITIONS; + errors++; + } else + lp->d_npartitions = v; + continue; + } + if (tp == NULL) + tp = ""; + if (streq(cp, "disk")) { + strncpy(lp->d_typename, tp, sizeof (lp->d_typename)); + continue; + } + if (streq(cp, "label")) { + strncpy(lp->d_packname, tp, sizeof (lp->d_packname)); + continue; + } + if (streq(cp, "bytes/sector")) { + v = atoi(tp); + if (v <= 0 || (v % 512) != 0) { + fprintf(stderr, + "line %d: %s: bad sector size\n", + lineno, tp); + errors++; + } else + lp->d_secsize = v; + continue; + } + if (streq(cp, "sectors/track")) { + v = atoi(tp); + if (v <= 0) { + fprintf(stderr, "line %d: %s: bad %s\n", + lineno, tp, cp); + errors++; + } else + lp->d_nsectors = v; + continue; + } + if (streq(cp, "sectors/cylinder")) { + v = atoi(tp); + if (v <= 0) { + fprintf(stderr, "line %d: %s: bad %s\n", + lineno, tp, cp); + errors++; + } else + lp->d_secpercyl = v; + continue; + } + if (streq(cp, "tracks/cylinder")) { + v = atoi(tp); + if (v <= 0) { + fprintf(stderr, "line %d: %s: bad %s\n", + lineno, tp, cp); + errors++; + } else + lp->d_ntracks = v; + continue; + } + if (streq(cp, "cylinders")) { + v = atoi(tp); + if (v <= 0) { + fprintf(stderr, "line %d: %s: bad %s\n", + lineno, tp, cp); + errors++; + } else + lp->d_ncylinders = v; + continue; + } + if (streq(cp, "rpm")) { + v = atoi(tp); + if (v <= 0) { + fprintf(stderr, "line %d: %s: bad %s\n", + lineno, tp, cp); + errors++; + } else + lp->d_rpm = v; + continue; + } + if (streq(cp, "interleave")) { + v = atoi(tp); + if (v <= 0) { + fprintf(stderr, "line %d: %s: bad %s\n", + lineno, tp, cp); + errors++; + } else + lp->d_interleave = v; + continue; + } + if (streq(cp, "trackskew")) { + v = atoi(tp); + if (v < 0) { + fprintf(stderr, "line %d: %s: bad %s\n", + lineno, tp, cp); + errors++; + } else + lp->d_trackskew = v; + continue; + } + if (streq(cp, "cylinderskew")) { + v = atoi(tp); + if (v < 0) { + fprintf(stderr, "line %d: %s: bad %s\n", + lineno, tp, cp); + errors++; + } else + lp->d_cylskew = v; + continue; + } + if (streq(cp, "headswitch")) { + v = atoi(tp); + if (v < 0) { + fprintf(stderr, "line %d: %s: bad %s\n", + lineno, tp, cp); + errors++; + } else + lp->d_headswitch = v; + continue; + } + if (streq(cp, "track-to-track seek")) { + v = atoi(tp); + if (v < 0) { + fprintf(stderr, "line %d: %s: bad %s\n", + lineno, tp, cp); + errors++; + } else + lp->d_trkseek = v; + continue; + } + if ('a' <= *cp && *cp <= 'z' && cp[1] == '\0') { + unsigned part = *cp - 'a'; + + if (part > lp->d_npartitions) { + fprintf(stderr, + "line %d: bad partition name\n", lineno); + errors++; + continue; + } + pp = &lp->d_partitions[part]; +#define NXTNUM(n) { \ + cp = tp, tp = word(cp); \ + if (tp == NULL) \ + tp = cp; \ + (n) = atoi(cp); \ + } + + NXTNUM(v); + if (v < 0) { + fprintf(stderr, + "line %d: %s: bad partition size\n", + lineno, cp); + errors++; + } else + pp->p_size = v; + NXTNUM(v); + if (v < 0) { + fprintf(stderr, + "line %d: %s: bad partition offset\n", + lineno, cp); + errors++; + } else + pp->p_offset = v; + cp = tp, tp = word(cp); + cpp = fstypenames; + for (; cpp < &fstypenames[FSMAXTYPES]; cpp++) + if ((s = *cpp) && streq(s, cp)) { + pp->p_fstype = cpp - fstypenames; + goto gottype; + } + if (isdigit(*cp)) + v = atoi(cp); + else + v = FSMAXTYPES; + if ((unsigned)v >= FSMAXTYPES) { + fprintf(stderr, "line %d: %s %s\n", lineno, + "Warning, unknown filesystem type", 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; + } + fprintf(stderr, "line %d: %s: Unknown disklabel field\n", + lineno, cp); + errors++; + next: + ; + } + errors += checklabel(lp); + return (errors == 0); +} + +/* + * Check disklabel for errors and fill in + * derived fields according to supplied values. + */ +checklabel(lp) + register struct disklabel *lp; +{ + register struct partition *pp; + int i, errors = 0; + char part; + + if (lp->d_secsize == 0) { + fprintf(stderr, "sector size %d\n", lp->d_secsize); + return (1); + } + if (lp->d_nsectors == 0) { + fprintf(stderr, "sectors/track %d\n", lp->d_nsectors); + return (1); + } + if (lp->d_ntracks == 0) { + fprintf(stderr, "tracks/cylinder %d\n", lp->d_ntracks); + return (1); + } + if (lp->d_ncylinders == 0) { + fprintf(stderr, "cylinders/unit %d\n", lp->d_ncylinders); + errors++; + } + if (lp->d_rpm == 0) + 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; + if (lp->d_bbsize == 0) { + fprintf(stderr, "boot block size %d\n", lp->d_bbsize); + errors++; + } else if (lp->d_bbsize % lp->d_secsize) + Warning("boot block size %% sector-size != 0"); + if (lp->d_sbsize == 0) { + fprintf(stderr, "super block size %d\n", lp->d_sbsize); + errors++; + } else if (lp->d_sbsize % lp->d_secsize) + Warning("super block size %% sector-size != 0"); + if (lp->d_npartitions > MAXPARTITIONS) + 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) + Warning("partition %c: size 0, but offset %d", + part, pp->p_offset); +#ifdef notdef + if (pp->p_size % lp->d_secpercyl) + Warning("partition %c: size %% cylinder-size != 0", + part); + if (pp->p_offset % lp->d_secpercyl) + Warning("partition %c: offset %% cylinder-size != 0", + part); +#endif + if (pp->p_offset > lp->d_secperunit) { + fprintf(stderr, + "partition %c: offset past end of unit\n", part); + errors++; + } + if (pp->p_offset + pp->p_size > lp->d_secperunit) { + fprintf(stderr, + "partition %c: partition extends past end of unit\n", + part); + errors++; + } + } + for (; i < MAXPARTITIONS; i++) { + part = 'a' + i; + pp = &lp->d_partitions[i]; + if (pp->p_size || pp->p_offset) + Warning("unused partition %c: size %d offset %d", + 'a' + i, pp->p_size, pp->p_offset); + } + return (errors); +} + +/* + * 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. + */ +setbootflag(lp) + register struct disklabel *lp; +{ + register 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) { + fprintf(stderr, + "boot overlaps used partition %c\n", + part); + errors++; + } else { + pp->p_fstype = FS_BOOT; + Warning("boot overlaps partition %c, %s", + part, "marked as FS_BOOT"); + } + } + } + if (errors) { + fprintf(stderr, "Cannot install boot program\n"); + exit(4); + } +} + +/*VARARGS1*/ +Warning(fmt, a1, a2, a3, a4, a5) + char *fmt; +{ + + fprintf(stderr, "Warning, "); + fprintf(stderr, fmt, a1, a2, a3, a4, a5); + fprintf(stderr, "\n"); +} + +Perror(str) + char *str; +{ + fputs("disklabel: ", stderr); perror(str); + exit(4); +} + +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 boot1 [ -s boot2 ] ] disk [ type ]", + "(to install boot program with existing label)", +"or disklabel -w -B [ -b boot1 [ -s boot2 ] ] disk type [ packid ]", + "(to write label and boot program)", +"or disklabel -R -B [ -b boot1 [ -s boot2 ] ] 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 0000000..f7a1e49 --- /dev/null +++ b/sbin/disklabel/dkcksum.c @@ -0,0 +1,53 @@ +/*- + * 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 +static char sccsid[] = "@(#)dkcksum.c 8.1 (Berkeley) 6/5/93"; +#endif /* not lint */ + +#include +#include + +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 0000000..def3297 --- /dev/null +++ b/sbin/disklabel/pathnames.h @@ -0,0 +1,40 @@ +/* + * 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 + +#define _PATH_BOOTDIR "/usr/mdec" +#undef _PATH_TMP +#define _PATH_TMP "/tmp/EdDk.aXXXXXX" -- cgit v1.1