Subject: Disklabels arrive for 2.11BSD (#252 part 3 of 18) Index: sys,bin,usr.lib,(many more)/ 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 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 \ , 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 YX#include YX#include YX#include YX#include YX#include YX#define DKTYPENAMES YX#include YX#include YX#include YX#include YX#include 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 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