[Midnightbsd-cvs] src [10473] trunk/sbin/sunlabel: add sunlabel

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Wed Jun 6 20:26:35 EDT 2018


Revision: 10473
          http://svnweb.midnightbsd.org/src/?rev=10473
Author:   laffer1
Date:     2018-06-06 20:26:34 -0400 (Wed, 06 Jun 2018)
Log Message:
-----------
add sunlabel

Added Paths:
-----------
    trunk/sbin/sunlabel/
    trunk/sbin/sunlabel/Makefile
    trunk/sbin/sunlabel/runtest.sh
    trunk/sbin/sunlabel/sunlabel.8
    trunk/sbin/sunlabel/sunlabel.c

Added: trunk/sbin/sunlabel/Makefile
===================================================================
--- trunk/sbin/sunlabel/Makefile	                        (rev 0)
+++ trunk/sbin/sunlabel/Makefile	2018-06-07 00:26:34 UTC (rev 10473)
@@ -0,0 +1,24 @@
+# $MidnightBSD$
+# $FreeBSD: stable/10/sbin/sunlabel/Makefile 211725 2010-08-23 22:24:11Z imp $
+
+.PATH: ${.CURDIR}/../../sys/geom
+
+PROG=	sunlabel
+SRCS=	sunlabel.c geom_sunlabel_enc.c
+MAN=	sunlabel.8
+
+.if ${MACHINE_CPUARCH} == "sparc64"
+LINKS=	${BINDIR}/sunlabel ${BINDIR}/disklabel
+MLINKS=	sunlabel.8 disklabel.8
+.endif
+
+DPADD=	${LIBGEOM}
+LDADD=	-lgeom
+
+.include <bsd.prog.mk>
+
+test:	${PROG}
+	sh ${.CURDIR}/runtest.sh
+
+testx: ${PROG}
+	sh -x ${.CURDIR}/runtest.sh


Property changes on: trunk/sbin/sunlabel/Makefile
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sbin/sunlabel/runtest.sh
===================================================================
--- trunk/sbin/sunlabel/runtest.sh	                        (rev 0)
+++ trunk/sbin/sunlabel/runtest.sh	2018-06-07 00:26:34 UTC (rev 10473)
@@ -0,0 +1,158 @@
+#!/bin/sh
+# $FreeBSD: stable/10/sbin/sunlabel/runtest.sh 113897 2003-04-23 08:25:44Z phk $
+# $MidnightBSD$
+
+TMP=/tmp/$$.
+set -e
+MD=`mdconfig -a -t malloc -s 2m`
+trap "exec 7</dev/null; rm -f ${TMP}* ; mdconfig -d -u ${MD}" EXIT INT TERM
+
+./sunlabel -r -w $MD auto
+
+dd if=/dev/$MD of=${TMP}i0 count=16 > /dev/null 2>&1
+./sunlabel $MD > ${TMP}l0
+
+sed '
+/  c:/{
+p
+s/c:/a:/
+s/3969/1024/
+}
+' ${TMP}l0 > ${TMP}l1
+
+./sunlabel -R $MD ${TMP}l1
+if [ -c /dev/${MD}a ] ; then
+	echo "PASS: Created a: partition" 1>&2
+else
+	echo "FAIL: Did not create a: partition" 1>&2
+	exit 2
+fi
+
+# Spoil and rediscover
+
+true > /dev/${MD}
+if [ -c /dev/${MD}a ] ; then
+	echo "PASS: Recreated a: partition after spoilage" 1>&2
+else
+	echo "FAIL: Did not recreate a: partition after spoilage" 1>&2
+	exit 2
+fi
+
+dd if=/dev/$MD of=${TMP}i1 count=16 > /dev/null 2>&1
+sed '
+/  c:/{
+p
+s/c:/a:/
+s/3969/2048/
+}
+' ${TMP}l0 > ${TMP}l2
+
+./sunlabel -R $MD ${TMP}l2
+dd if=/dev/$MD of=${TMP}i2 count=16 > /dev/null 2>&1
+
+exec 7< /dev/${MD}a
+
+for t in a c
+do
+	if dd if=${TMP}i2 of=/dev/${MD}$t 2>/dev/null ; then
+		echo "PASS: Could rewrite same label to ...$t while ...a open" 1>&2
+	else
+		echo "FAIL: Could not rewrite same label to ...$t while ...a open" 1>&2
+		exit 2
+	fi
+
+	if dd if=${TMP}i1 of=/dev/${MD}$t 2>/dev/null ; then
+		echo "FAIL: Could label with smaller ...a to ...$t while ...a open" 1>&2
+		exit 2
+	else
+		echo "PASS: Could not label with smaller ...a to ...$t while ...a open" 1>&2
+	fi
+
+	if dd if=${TMP}i0 of=/dev/${MD}$t 2>/dev/null ; then
+		echo "FAIL: Could write label missing ...a to ...$t while ...a open" 1>&2
+		exit 2
+	else
+		echo "PASS: Could not write label missing ...a to ...$t while ...a open" 1>&2
+	fi
+done
+
+exec 7< /dev/null
+
+if dd if=${TMP}i0 of=/dev/${MD}c 2>/dev/null ; then
+	echo "PASS: Could write missing ...a label to ...c" 1>&2
+else
+	echo "FAIL: Could not write missing ...a label to ...c" 1>&2
+	exit 2
+fi
+
+if dd if=${TMP}i2 of=/dev/${MD}c 2>/dev/null ; then
+	echo "PASS: Could write large ...a label to ...c" 1>&2
+else
+	echo "FAIL: Could not write large ...a label to ...c" 1>&2
+	exit 2
+fi
+
+if dd if=${TMP}i1 of=/dev/${MD}c 2>/dev/null ; then
+	echo "PASS: Could write small ...a label to ...c" 1>&2
+else
+	echo "FAIL: Could not write small ...a label to ...c" 1>&2
+	exit 2
+fi
+
+if dd if=${TMP}i2 of=/dev/${MD}a 2>/dev/null ; then
+	echo "PASS: Could increase size of ...a by writing to ...a" 1>&2
+else
+	echo "FAIL: Could not increase size of ...a by writing to ...a" 1>&2
+	exit 2
+fi
+
+if dd if=${TMP}i1 of=/dev/${MD}a 2>/dev/null ; then
+	echo "FAIL: Could decrease size of ...a by writing to ...a" 1>&2
+	exit 2
+else
+	echo "PASS: Could not decrease size of ...a by writing to ...a" 1>&2
+fi
+
+if dd if=${TMP}i0 of=/dev/${MD}a 2>/dev/null ; then
+	echo "FAIL: Could delete ...a by writing to ...a" 1>&2
+	exit 2
+else
+	echo "PASS: Could not delete ...a by writing to ...a" 1>&2
+fi
+
+if ./sunlabel -B -b ${TMP}i0 ${MD} ; then
+	if [ ! -c /dev/${MD}a ] ; then
+		echo "FAILED: Writing bootcode killed ...a" 1>&2
+		exit 2
+	else
+		echo "PASS: Could write bootcode while closed" 1>&2
+	fi
+else
+	echo "FAILED: Could not write bootcode while closed" 1>&2
+	exit 2
+fi
+
+exec 7> /dev/${MD}c
+if ktrace ./sunlabel -B -b ${TMP}i0 ${MD} ; then
+	if [ ! -c /dev/${MD}a ] ; then
+		echo "FAILED: Writing bootcode killed ...a" 1>&2
+		exit 2
+	else
+		echo "PASS: Could write bootcode while open" 1>&2
+	fi
+else
+	echo "FAILED: Could not write bootcode while open" 1>&2
+	exit 2
+fi
+exec 7> /dev/null
+
+if dd if=${TMP}i0 of=/dev/${MD}c 2>/dev/null ; then
+	echo "PASS: Could delete ...a by writing to ...c" 1>&2
+else
+	echo "FAIL: Could not delete ...a by writing to ...c" 1>&2
+	exit 2
+fi
+
+# XXX: need to add a 'b' partition and check for overlaps.
+
+exit 0


Property changes on: trunk/sbin/sunlabel/runtest.sh
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sbin/sunlabel/sunlabel.8
===================================================================
--- trunk/sbin/sunlabel/sunlabel.8	                        (rev 0)
+++ trunk/sbin/sunlabel/sunlabel.8	2018-06-07 00:26:34 UTC (rev 10473)
@@ -0,0 +1,433 @@
+.\" $MidnightBSD$
+.\" Copyright (c) 2004
+.\"	David E. O'Brien.  All rights reserved.
+.\" Copyright (c) 2004, 2005
+.\"	Joerg Wunsch.  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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+.\"
+.\" $FreeBSD: stable/10/sbin/sunlabel/sunlabel.8 233992 2012-04-07 09:05:30Z joel $
+.\"
+.Dd March 30, 2005
+.Dt SUNLABEL 8
+.Os
+.Sh NAME
+.Nm sunlabel
+.Nd read and write disk pack label suitable for Sun's OpenBoot PROM
+.Sh SYNOPSIS
+.Nm
+.Op Fl r
+.Op Fl c No \&| Fl h
+.Ar disk
+.Nm
+.Fl B
+.Op Fl b Ar boot1
+.Op Fl n
+.Ar disk
+.Nm
+.Fl R
+.Op Fl B Op Fl b Ar boot1
+.Op Fl r
+.Op Fl n
+.Op Fl c
+.Ar disk protofile
+.Nm
+.Fl e
+.Op Fl B Op Fl b Ar boot1
+.Op Fl r
+.Op Fl n
+.Op Fl c
+.Ar disk
+.Nm
+.Fl w
+.Op Fl B Op Fl b Ar boot1
+.Op Fl r
+.Op Fl n
+.Op Fl c
+.Ar disk type
+.Sh DESCRIPTION
+The
+.Nm
+utility
+installs, examines or modifies the
+.Em Sun OpenBoot PROM
+label on a disk.
+In addition,
+.Nm
+can install bootstrap code.
+.Ss Introduction
+The label occupies the first sector (i.e., 512 bytes) of each disk.
+It starts with a textual description which by convention also mentions
+the disk geometry in textual form (number of cylinders, alternate
+cylinders, heads, and sectors per track), optionally followed by a
+table of SVR4-compatible VTOC tags and flags per partition, followed
+by the partition table itself.
+Finally, a checksum is recorded to ensure the label has not been
+tampered with.
+.Pp
+The
+.Em Sun OpenBoot PROM
+label allows for 8 disk partitions.
+The partition table lists the starting cylinder of the partition,
+plus the size of the partition in 512-byte sectors.
+Thus, partitions in the
+.Em Sun OpenBoot PROM
+must always start at a cylinder boundary (for whatever geometry
+emulation has been chosen).
+.Pp
+The optional SVR4-compatible VTOC tag and flags table is not used
+by the
+.Fx
+kernel.
+It is maintained solely for compatibility with the
+.Tn Solaris
+operating system that might share disks with
+.Fx
+on the same hardware platform.
+.Pp
+The
+.Em Sun OpenBoot PROM
+label is natively understood by the underlying hardware, which can
+bootstrap from a single partition entry, as opposed to the very first
+block(s) of the entire disk as on many other hardware platforms.
+.Pp
+Note that the hardware platform mandates that two cylinders are set
+aside as
+.Em alternate cylinders
+which are not available to user programs (and not even through the
+.Dq Li backup
+partition).
+.Ss Options
+Options are listed in alphabetical order here.
+Note that only those option combinations listed under
+.Sx SYNOPSIS
+are allowable.
+.Bl -tag -width ".Fl b Ar bootpath"
+.It Fl b Ar bootpath
+Specify that
+.Ar bootpath
+is to be used as the boot image, rather than the default of
+.Pa /boot/boot1 .
+.It Fl B
+Install bootstrap code onto the disk.
+Note that since the underlying hardware platform bootstraps from
+partitions, not disks, this operation is only useful if there is
+a partition starting at offset 0.
+.It Fl c
+Use cylinders for partition size display rather than
+(512-byte) sectors.
+This also changes the default interpretation of the partition
+size entries when editing the label, or reading from a prototype
+file.
+Thus, prototype files are only compatible when both, obtaining
+the file and re-installing it is done using the same
+.Fl c
+option setting.
+.It Fl e
+Enter edit mode.
+See
+.Sx Edit mode
+below for a more detailed explanation.
+.It Fl h
+When displaying the label, make the partition size and offset
+values
+.Dq human readable .
+The displayed numbers will get a suffix of
+.Ql B
+for bytes,
+.Ql K
+for 1024 bytes each,
+.Ql M
+for 1048576 bytes each, or
+.Ql G
+for 1073741824 bytes each appended.
+Note that due to possible rounding errors, prototype files
+obtained using the
+.Fl h
+option are not suited for re-installing using the
+.Fl R
+option.
+.It Fl n
+No changes.
+All operations, checks etc., are performed normally, but nothing
+is written to disk.
+.It Fl r
+Obsolete option that used to indicate that the operation should
+be done directly on disk, as opposed through the respective kernel
+services.
+Ignored.
+.It Fl R
+Restore label from the prototype in
+.Ar protofile .
+A prototype file is simply the textual representation of the
+label as printed using the first form of the
+.Nm
+utility shown in the
+.Sx SYNOPSIS .
+Note that the
+.Fl c
+option used to obtain the prototype must match the option used
+when restoring the label (both present, or both absent).
+.It Fl w
+Write mode.
+Suitable to write an initial label to disk.
+The
+.Ar type
+argument used to be an entry into a table of predefined labels,
+but this functionality is not supported by
+.Nm .
+Instead, the only allowable
+.Ar type
+argument is the string
+.Dq Li auto ,
+indicating that an automatically created label should be written
+to disk.
+This automatism will try to create an initial label that fits as
+best as possible into the available disk capacity.
+.El
+.Pp
+If neither of the
+.Fl e , R ,
+or
+.Fl w
+options are present, the existing label for
+.Ar disk
+will be printed to standard output.
+.Pp
+The
+.Ar disk
+argument
+must be given as a plain disk name, without any leading
+.Pa /dev/ .
+.Ss Edit mode
+In edit mode, the existing label from
+.Ar disk
+will be read, and put into a template file.
+The command referenced by the
+.Ev EDITOR
+environmental variable will be started to allow the user
+to edit the label.
+The label is then checked and examined for any errors.
+If no errors have been found, the new label is written to disk.
+If there were any errors, a message is printed to standard
+error output, and the user is given the opportunity to edit
+the template file again.
+If accepted, editing starts over.
+If declined, no changes will
+be written to disk.
+.Pp
+The label presented for editing is the same as the standard
+printout, with some added hints about the possible options to
+specify the sector size and starting cylinder.
+The following areas in the template can be edited:
+.Bl -tag -width indent
+.It Sy Textual label, geometry emulation
+The line
+.D1 Li text: Ar XXXX Li cyl Ar CC Li alt 2 hd Ar HH Li sec Ar SS
+represents the label text.
+It must be retained exactly in the form shown.
+The editable text
+.Ar XXXX
+is a simple (non-whitespace) text describing the disk.
+By convention, this text mentions the approximate size of the
+disk, as in
+.Dq Li SUN9.0G
+for a 9 GB disk shipped by Sun.
+.Pp
+The values
+.Ar CC ,
+.Ar HH ,
+and
+.Ar SS
+describe the number of cylinders, heads (tracks per
+cylinder), and sectors per track respectively.
+They might be modified to change the geometry emulation.
+Each number must be between 1 and 65535.
+The product
+.D1 Em (CC + 2) * HH * SS
+must be less than or equal to the total number of sectors of the
+disk (which is given as a hint in a comment field).
+.It Sy Volume name
+The volume name (if present) is introduced by the string
+.Dq "volume name:" .
+It can be up to 8 characters long, and might be useful to distinguish
+different disks in a system.
+Note that volume names require the VTOC elements to be present, so
+any of the VTOC constraints described below need to be obeyed as well
+if a volume name is to be set.
+Setting an empty volume name will delete it from the label.
+.It Sy Partition entries
+Partition entries start with a letter from
+.Ql a
+through
+.Ql h ,
+immediately followed by a colon, followed by the size of this
+partition, and the starting cylinder of the partition.
+The unit of the size field defaults to sectors, or to cylinders
+if the
+.Fl c
+option is in effect.
+Alternatively, a different unit may be specified by appending
+.Ql s
+for (512-byte) sectors,
+.Ql c
+for cylinders,
+.Ql k
+for kilobytes,
+.Ql m
+for megabytes, or
+.Ql g
+for gigabytes.
+The last partition entry may specify the size as
+.Ql *
+to indicate that this entry should consume the rest of disk not
+consumed by any other partition so far.
+.Pp
+The start of partition is always taken as a cylinder number (starting
+at 0) since this is what the underlying hardware uses.
+Alternatively, specifying it as
+.Ql *
+will make the computation automatically chose the nearest possible
+cylinder boundary.
+.Pp
+Partition
+.Ql c
+must always be present, must start at 0, and must cover the entire
+disk (without considering the alternate cylinders though).
+.Pp
+Optionally, each partition entry may be followed by an SVR4-compatible
+VTOC tag name, and a flag description.
+The following VTOC tag names are known:
+.Bl -column -offset indent ".Li unassigned" ".Sy value" ".Sy comment"
+.It Sy name Ta Sy value Ta Sy comment
+.It Li unassigned Ta No 0x00 Ta \&
+.It Li boot Ta No 0x01 Ta \&
+.It Li root Ta No 0x02 Ta \&
+.It Li swap Ta No 0x03 Ta \&
+.It Li usr Ta No 0x04 Ta \&
+.It Li backup Ta No 0x05 Ta c partition, entire disk
+.It Li stand Ta No 0x06 Ta \&
+.It Li var Ta No 0x07 Ta \&
+.It Li home Ta No 0x08 Ta \&
+.It Li altsctr Ta No 0x09 Ta alternate sector partition
+.It Li cache Ta No 0x0a Ta Solaris cachefs partition
+.It Li VxVM_pub Ta No 0x0e Ta VxVM public region
+.It Li VxVM_priv Ta No 0x0f Ta VxVM private region
+.El
+.Pp
+The following VTOC flags are known:
+.Bl -column -offset indent ".Sy name" ".Sy value" ".Sy comment"
+.It Sy name Ta Sy value Ta Sy comment
+.It Li wm Ta No 0x00 Ta read/write, mountable
+.It Li wu Ta No 0x01 Ta read/write, unmountable
+.It Li rm Ta No 0x10 Ta read/only, mountable
+.It Li ru Ta No 0x11 Ta read/only, unmountable
+.El
+.Pp
+Optionally, both the tag and/or the flag name may be specified
+numerically, using standard
+.Ql C
+numerical notation (prefix
+.Ql 0x
+for hexadecimal numbers,
+.Ql 0
+for octal numbers).
+If the flag field is omitted, it defaults to
+.Ql wm .
+If the tag field is also omitted, it defaults to
+.Dq Li unassigned .
+If none of the partitions lists any VTOC tag/flags, no
+SVR4-compatible VTOC elements will be written to disk.
+If VTOC-style elements are present, partition
+.Ql c
+must be marked as
+.Dq Li backup
+(and should be marked
+.Ql wu ) .
+.El
+.Pp
+When checking the label, partition
+.Ql c
+is checked for presence, and for the mentioned restrictions.
+All other partitions are checked for possible overlaps, as
+well as for not extending past the end of unit.
+If VTOC-style elements are present, overlaps of unmountable
+partitions against other partitions will be warned still but
+do not cause a rejection of the label.
+That way,
+.Em encapsulated disks
+of volume management software are acceptable as long as the
+volume management partitions are clearly marked as unmountable.
+.Pp
+Any other fields in the label template are informational only,
+and will not be parsed when reading the label.
+.Pp
+Note that when changing the geometry emulation by editing the
+textual description line, all partition entries will be
+considered based on the new geometry emulation.
+.Sh ENVIRONMENT
+.Bl -tag -width ".Ev EDITOR" -compact
+.It Ev EDITOR
+Name of the command to edit the template file in edit-mode.
+Defaults to
+.Xr vi 1 .
+.El
+.Sh FILES
+.Bl -tag -width ".Pa /boot/boot1" -compact
+.It Pa /boot/boot1
+Default boot image.
+.El
+.Sh SEE ALSO
+.Xr vi 1 ,
+.Xr geom 4 ,
+.Xr bsdlabel 8
+.Sh HISTORY
+The
+.Nm
+utility appeared in
+.Fx 5.1 .
+.Sh AUTHORS
+The
+.Nm
+utility was written by
+.An Jake Burkholder ,
+modeling it after the
+.Xr bsdlabel 8
+command available on other architectures.
+.Pp
+.An -nosplit
+This man page was initially written by
+.An David O'Brien ,
+and later substantially updated by
+.An J\(:org Wunsch .
+.Sh BUGS
+Installing bootstrap code onto an entire disk is merely pointless.
+.Nm
+should rather support installing bootstrap code into a partition
+instead.
+.Pp
+The
+.Dq auto
+layout algorithm could be smarter.
+By now, it tends to emulate fairly large cylinders which due to
+the two reserved alternate cylinders causes a fair amount of
+wasted disk space.


Property changes on: trunk/sbin/sunlabel/sunlabel.8
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property
Added: trunk/sbin/sunlabel/sunlabel.c
===================================================================
--- trunk/sbin/sunlabel/sunlabel.c	                        (rev 0)
+++ trunk/sbin/sunlabel/sunlabel.c	2018-06-07 00:26:34 UTC (rev 10473)
@@ -0,0 +1,1008 @@
+/* $MidnightBSD$ */
+/*-
+ * Copyright (c) 2003 Jake Burkholder.
+ * Copyright (c) 2004,2005 Joerg Wunsch.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+/*
+ * Copyright (c) 1994, 1995 Gordon W. Ross
+ * Copyright (c) 1994 Theo de Raadt
+ * All rights reserved.
+ * 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.
+ *      This product includes software developed by Theo de Raadt.
+ * 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.
+ *
+ *	from: $NetBSD: disksubr.c,v 1.13 2000/12/17 22:39:18 pk $
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: stable/10/sbin/sunlabel/sunlabel.c 144328 2005-03-30 09:33:10Z joerg $");
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/disk.h>
+#include <sys/ioctl.h>
+#include <sys/sun_disklabel.h>
+#include <sys/wait.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <libgeom.h>
+#include <paths.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define	_PATH_TMPFILE	"/tmp/EdDk.XXXXXXXXXX"
+#define	_PATH_BOOT	"/boot/boot1"
+
+static int bflag;
+static int Bflag;
+static int cflag;
+static int eflag;
+static int hflag;
+static int nflag;
+static int Rflag;
+static int wflag;
+
+static off_t mediasize;
+static uint32_t sectorsize;
+
+struct tags {
+	const char *name;
+	unsigned int id;
+};
+
+static int check_label(struct sun_disklabel *sl);
+static void read_label(struct sun_disklabel *sl, const char *disk);
+static void write_label(struct sun_disklabel *sl, const char *disk,
+    const char *bootpath);
+static void edit_label(struct sun_disklabel *sl, const char *disk,
+    const char *bootpath);
+static int parse_label(struct sun_disklabel *sl, const char *file);
+static void print_label(struct sun_disklabel *sl, const char *disk, FILE *out);
+
+static int parse_size(struct sun_disklabel *sl, int part, char *size);
+static int parse_offset(struct sun_disklabel *sl, int part, char *offset);
+
+static const char *flagname(unsigned int tag);
+static const char *tagname(unsigned int tag);
+static unsigned int parse_flag(struct sun_disklabel *sl, int part,
+			       const char *flag);
+static unsigned int parse_tag(struct sun_disklabel *sl, int part,
+			      const char *tag);
+static const char *make_h_number(uintmax_t u);
+
+static void usage(void);
+
+extern char *__progname;
+
+static struct tags knowntags[] = {
+	{ "unassigned",	VTOC_UNASSIGNED },
+	{ "boot",	VTOC_BOOT },
+	{ "root",	VTOC_ROOT },
+	{ "swap",	VTOC_SWAP },
+	{ "usr",	VTOC_USR },
+	{ "backup",	VTOC_BACKUP },
+	{ "stand",	VTOC_STAND },
+	{ "var",	VTOC_VAR },
+	{ "home",	VTOC_HOME },
+	{ "altsctr",	VTOC_ALTSCTR },
+	{ "cache",	VTOC_CACHE },
+	{ "VxVM_pub",	VTOC_VXVM_PUB },
+	{ "VxVM_priv",	VTOC_VXVM_PRIV },
+};
+
+static struct tags knownflags[] = {
+	{ "wm", 0 },
+	{ "wu", VTOC_UNMNT },
+	{ "rm", VTOC_RONLY },
+	{ "ru", VTOC_UNMNT | VTOC_RONLY },
+};
+
+/*
+ * Disk label editor for sun disklabels.
+ */
+int
+main(int ac, char **av)
+{
+	struct sun_disklabel sl;
+	const char *bootpath;
+	const char *proto;
+	const char *disk;
+	int ch;
+
+	bootpath = _PATH_BOOT; 
+	while ((ch = getopt(ac, av, "b:BcehnrRw")) != -1)
+		switch (ch) {
+		case 'b':
+			bflag = 1;
+			bootpath = optarg;
+			break;
+		case 'B':
+			Bflag = 1;
+			break;
+		case 'c':
+			cflag = 1;
+			break;
+		case 'e':
+			eflag = 1;
+			break;
+		case 'h':
+			hflag = 1;
+			break;
+		case 'n':
+			nflag = 1;
+			break;
+		case 'r':
+			fprintf(stderr, "Obsolete -r flag ignored\n");
+			break;
+		case 'R':
+			Rflag = 1;
+			break;
+		case 'w':
+			wflag = 1;
+			break;
+		default:
+			usage();
+			break;
+		}
+	if (bflag && !Bflag)
+		usage();
+	if (nflag && !(Bflag || eflag || Rflag || wflag))
+		usage();
+	if (eflag && (Rflag || wflag))
+		usage();
+	if (eflag)
+		hflag = 0;
+	ac -= optind;
+	av += optind;
+	if (ac == 0)
+		usage();
+	bzero(&sl, sizeof(sl));
+	disk = av[0];
+	if (wflag) {
+		if (ac != 2 || strcmp(av[1], "auto") != 0)
+			usage();
+		read_label(&sl, disk);
+		bzero(sl.sl_part, sizeof(sl.sl_part));
+		sl.sl_part[SUN_RAWPART].sdkp_cyloffset = 0;
+		sl.sl_part[SUN_RAWPART].sdkp_nsectors = sl.sl_ncylinders *
+		    sl.sl_ntracks * sl.sl_nsectors;
+		write_label(&sl, disk, bootpath);
+	} else if (eflag) {
+		if (ac != 1)
+			usage();
+		read_label(&sl, disk);
+		if (sl.sl_magic != SUN_DKMAGIC)
+			errx(1, "%s%s has no sun disklabel", _PATH_DEV, disk);
+		edit_label(&sl, disk, bootpath);
+	} else if (Rflag) {
+		if (ac != 2)
+			usage();
+		proto = av[1];
+		read_label(&sl, disk);
+		if (parse_label(&sl, proto) != 0)
+			errx(1, "%s: invalid label", proto);
+		write_label(&sl, disk, bootpath);
+	} else if (Bflag) {
+		read_label(&sl, disk);
+		if (sl.sl_magic != SUN_DKMAGIC)
+			errx(1, "%s%s has no sun disklabel", _PATH_DEV, disk);
+		write_label(&sl, disk, bootpath);
+	} else {
+		read_label(&sl, disk);
+		if (sl.sl_magic != SUN_DKMAGIC)
+			errx(1, "%s%s has no sun disklabel", _PATH_DEV, disk);
+		print_label(&sl, disk, stdout);
+	}
+	return (0);
+}
+
+static int
+check_label(struct sun_disklabel *sl)
+{
+	uint64_t nsectors;
+	uint64_t ostart;
+	uint64_t start;
+	uint64_t oend;
+	uint64_t end;
+	int havevtoc;
+	int warnonly;
+	int i;
+	int j;
+
+	havevtoc = sl->sl_vtoc_sane == SUN_VTOC_SANE;
+
+	nsectors = sl->sl_ncylinders * sl->sl_ntracks * sl->sl_nsectors;
+	if (sl->sl_part[SUN_RAWPART].sdkp_cyloffset != 0 ||
+	    sl->sl_part[SUN_RAWPART].sdkp_nsectors != nsectors) {
+		warnx("partition c is incorrect, must start at 0 and cover "
+		    "whole disk");
+		return (1);
+	}
+	if (havevtoc && sl->sl_vtoc_map[2].svtoc_tag != VTOC_BACKUP) {
+		warnx("partition c must have tag \"backup\"");
+		return (1);
+	}
+	for (i = 0; i < SUN_NPART; i++) {
+		if (i == 2 || sl->sl_part[i].sdkp_nsectors == 0)
+			continue;
+		start = (uint64_t)sl->sl_part[i].sdkp_cyloffset *
+		    sl->sl_ntracks * sl->sl_nsectors;
+		end = start + sl->sl_part[i].sdkp_nsectors;
+		if (end > nsectors) {
+			warnx("partition %c extends past end of disk",
+			    'a' + i);
+			return (1);
+		}
+		if (havevtoc) {
+			if (sl->sl_vtoc_map[i].svtoc_tag == VTOC_BACKUP) {
+				warnx("only partition c is allowed to have "
+				    "tag \"backup\"");
+				return (1);
+			}
+		}
+		for (j = 0; j < SUN_NPART; j++) {
+			/* 
+			 * Overlaps for unmountable partitions are
+			 * non-fatal but will be warned anyway.
+			 */
+			warnonly = havevtoc &&
+				((sl->sl_vtoc_map[i].svtoc_flag & VTOC_UNMNT) != 0 ||
+				 (sl->sl_vtoc_map[j].svtoc_flag & VTOC_UNMNT) != 0);
+
+			if (j == 2 || j == i ||
+			    sl->sl_part[j].sdkp_nsectors == 0)
+				continue;
+			ostart = (uint64_t)sl->sl_part[j].sdkp_cyloffset *
+			    sl->sl_ntracks * sl->sl_nsectors;
+			oend = ostart + sl->sl_part[j].sdkp_nsectors;
+			if ((start <= ostart && end >= oend) ||
+			    (start > ostart && start < oend) ||
+			    (end > ostart && end < oend)) {
+				warnx("partition %c overlaps partition %c",
+				    'a' + i, 'a' + j);
+				if (!warnonly)
+					return (1);
+			}
+		}
+	}
+	return (0);
+}
+
+static void
+read_label(struct sun_disklabel *sl, const char *disk)
+{
+	char path[MAXPATHLEN];
+	uint32_t fwsectors;
+	uint32_t fwheads;
+	char buf[SUN_SIZE];
+	int fd, error;
+
+	snprintf(path, sizeof(path), "%s%s", _PATH_DEV, disk);
+	if ((fd = open(path, O_RDONLY)) < 0)
+		err(1, "open %s", path);
+	if (read(fd, buf, sizeof(buf)) != sizeof(buf))
+		err(1, "read");
+	error = sunlabel_dec(buf, sl);
+	if (ioctl(fd, DIOCGMEDIASIZE, &mediasize) != 0)
+		if (error)
+			err(1, "%s: ioctl(DIOCGMEDIASIZE) failed", disk);
+	if (ioctl(fd, DIOCGSECTORSIZE, &sectorsize) != 0) {
+		if (error)
+			err(1, "%s: DIOCGSECTORSIZE failed", disk);
+		else
+			sectorsize = 512;
+	}
+	if (error) {
+		bzero(sl, sizeof(*sl));
+		if (ioctl(fd, DIOCGFWSECTORS, &fwsectors) != 0)
+			fwsectors = 63;
+		if (ioctl(fd, DIOCGFWHEADS, &fwheads) != 0) {
+			if (mediasize <= 63 * 1024 * sectorsize)
+				fwheads = 1;
+			else if (mediasize <= 63 * 16 * 1024 * sectorsize)
+				fwheads = 16;
+			else
+				fwheads = 255;
+		}
+		sl->sl_rpm = 3600;
+		sl->sl_pcylinders = mediasize / (fwsectors * fwheads *
+		    sectorsize);
+		sl->sl_sparespercyl = 0;
+		sl->sl_interleave = 1;
+		sl->sl_ncylinders = sl->sl_pcylinders - 2;
+		sl->sl_acylinders = 2;
+		sl->sl_nsectors = fwsectors;
+		sl->sl_ntracks = fwheads;
+		sl->sl_part[SUN_RAWPART].sdkp_cyloffset = 0;
+		sl->sl_part[SUN_RAWPART].sdkp_nsectors = sl->sl_ncylinders *
+		    sl->sl_ntracks * sl->sl_nsectors;
+		if (mediasize > (off_t)4999L * 1024L * 1024L) {
+			sprintf(sl->sl_text,
+			    "FreeBSD%jdG cyl %u alt %u hd %u sec %u",
+			    (intmax_t)(mediasize + 512 * 1024 * 1024) /
+			        (1024 * 1024 * 1024),
+			    sl->sl_ncylinders, sl->sl_acylinders,
+			    sl->sl_ntracks, sl->sl_nsectors);
+		} else {
+			sprintf(sl->sl_text,
+			    "FreeBSD%jdM cyl %u alt %u hd %u sec %u",
+			    (intmax_t)(mediasize + 512 * 1024) / (1024 * 1024),
+			    sl->sl_ncylinders, sl->sl_acylinders,
+			    sl->sl_ntracks, sl->sl_nsectors);
+		}
+	}
+	close(fd);
+}
+
+static void
+write_label(struct sun_disklabel *sl, const char *disk, const char *bootpath)
+{
+	char path[MAXPATHLEN];
+	char boot[SUN_BOOTSIZE];
+	char buf[SUN_SIZE];
+	const char *errstr;
+	off_t off;
+	int bfd;
+	int fd;
+	int i;
+	struct gctl_req *grq;
+
+	sl->sl_magic = SUN_DKMAGIC;
+
+	if (check_label(sl) != 0)
+		errx(1, "invalid label");
+
+	bzero(buf, sizeof(buf));
+	sunlabel_enc(buf, sl);
+
+	if (nflag) {
+		print_label(sl, disk, stdout);
+		return;
+	}
+	if (Bflag) {
+		if ((bfd = open(bootpath, O_RDONLY)) < 0)
+			err(1, "open %s", bootpath);
+		i = read(bfd, boot, sizeof(boot));
+		if (i < 0)
+			err(1, "read");
+		else if (i != sizeof (boot))
+			errx(1, "read wrong size boot code (%d)", i);
+		close(bfd);
+	}
+	snprintf(path, sizeof(path), "%s%s", _PATH_DEV, disk);
+	fd = open(path, O_RDWR);
+	if (fd < 0) {
+		grq = gctl_get_handle();
+		gctl_ro_param(grq, "verb", -1, "write label");
+		gctl_ro_param(grq, "class", -1, "SUN");
+		gctl_ro_param(grq, "geom", -1, disk);
+		gctl_ro_param(grq, "label", sizeof buf, buf);
+		errstr = gctl_issue(grq);
+		if (errstr != NULL)
+			errx(1, "%s", errstr);
+		gctl_free(grq);
+		if (Bflag) {
+			grq = gctl_get_handle();
+			gctl_ro_param(grq, "verb", -1, "write bootcode");
+			gctl_ro_param(grq, "class", -1, "SUN");
+			gctl_ro_param(grq, "geom", -1, disk);
+			gctl_ro_param(grq, "bootcode", sizeof boot, boot);
+			errstr = gctl_issue(grq);
+			if (errstr != NULL)
+				errx(1, "%s", errstr);
+			gctl_free(grq);
+		}
+	} else {
+		if (lseek(fd, 0, SEEK_SET) < 0)
+			err(1, "lseek");
+		if (write(fd, buf, sizeof(buf)) != sizeof(buf))
+			err (1, "write");
+		if (Bflag) {
+			for (i = 0; i < SUN_NPART; i++) {
+				if (sl->sl_part[i].sdkp_nsectors == 0)
+					continue;
+				off = sl->sl_part[i].sdkp_cyloffset *
+				    sl->sl_ntracks * sl->sl_nsectors * 512;
+				/*
+				 * Ignore first SUN_SIZE bytes of boot code to
+				 * avoid overwriting the label.
+				 */
+				if (lseek(fd, off + SUN_SIZE, SEEK_SET) < 0)
+					err(1, "lseek");
+				if (write(fd, boot + SUN_SIZE,
+				    sizeof(boot) - SUN_SIZE) !=
+				    sizeof(boot) - SUN_SIZE)
+					err(1, "write");
+			}
+		}
+		close(fd);
+	}
+	exit(0);
+}
+
+static void
+edit_label(struct sun_disklabel *sl, const char *disk, const char *bootpath)
+{
+	char tmpfil[] = _PATH_TMPFILE;
+	const char *editor;
+	int status;
+	FILE *fp;
+	pid_t pid;
+	pid_t r;
+	int fd;
+	int c;
+
+	if ((fd = mkstemp(tmpfil)) < 0)
+		err(1, "mkstemp");
+	if ((fp = fdopen(fd, "w")) == NULL)
+		err(1, "fdopen");
+	print_label(sl, disk, fp);
+	fflush(fp);
+	for (;;) {
+		if ((pid = fork()) < 0)
+			err(1, "fork");
+		if (pid == 0) {
+			if ((editor = getenv("EDITOR")) == NULL)
+				editor = _PATH_VI;
+			execlp(editor, editor, tmpfil, (char *)NULL);
+			err(1, "execlp %s", editor);
+		}
+		status = 0;
+		while ((r = wait(&status)) > 0 && r != pid)
+			;
+		if (WIFEXITED(status)) {
+			if (parse_label(sl, tmpfil) == 0) {
+				fclose(fp);
+				unlink(tmpfil);
+				write_label(sl, disk, bootpath);
+				return;
+			}
+			printf("re-edit the label? [y]: ");
+			fflush(stdout);
+			c = getchar();
+			if (c != EOF && c != '\n')
+				while (getchar() != '\n')
+					;
+			if  (c == 'n') {
+				fclose(fp);
+				unlink(tmpfil);
+				return;
+			}
+		}
+	}
+	fclose(fp);
+	unlink(tmpfil);
+	return;
+}
+
+static int
+parse_label(struct sun_disklabel *sl, const char *file)
+{
+	char offset[32];
+	char size[32];
+	char flag[32];
+	char tag[32];
+	char buf[128];
+	char text[128];
+	char volname[SUN_VOLNAME_LEN + 1];
+	struct sun_disklabel sl1;
+	char *bp;
+	const char *what;
+	uint8_t part;
+	FILE *fp;
+	int line;
+	int rv;
+	int wantvtoc;
+	unsigned alt, cyl, hd, nr, sec;
+
+	line = wantvtoc = 0;
+	if ((fp = fopen(file, "r")) == NULL)
+		err(1, "fopen");
+	sl1 = *sl;
+	bzero(&sl1.sl_part, sizeof(sl1.sl_part));
+	while (fgets(buf, sizeof(buf), fp) != NULL) {
+		/*
+		 * In order to recognize a partition entry, we search
+		 * for lines starting with a single letter followed by
+		 * a colon as their first non-white characters.  We
+		 * silently ignore any other lines, so any comment etc.
+		 * lines in the label template will be ignored.
+		 *
+		 * XXX We should probably also recognize the geometry
+		 * fields on top, and allow changing the geometry
+		 * emulated by this disk.
+		 */
+		for (bp = buf; isspace(*bp); bp++)
+			;
+		if (strncmp(bp, "text:", strlen("text:")) == 0) {
+			bp += strlen("text:");
+			rv = sscanf(bp,
+			    " %s cyl %u alt %u hd %u sec %u",
+			    text, &cyl, &alt, &hd, &sec);
+			if (rv != 5) {
+				warnx("%s, line %d: text label does not "
+				    "contain required fields",
+				    file, line + 1);
+				fclose(fp);
+				return (1);
+			}
+			if (alt != 2) {
+				warnx("%s, line %d: # alt must be equal 2",
+				    file, line + 1);
+				fclose(fp);
+				return (1);
+			}
+			if (cyl == 0 || cyl > USHRT_MAX) {
+				what = "cyl";
+				nr = cyl;
+			unreasonable:
+				warnx("%s, line %d: # %s %d unreasonable",
+				    file, line + 1, what, nr);
+				fclose(fp);
+				return (1);
+			}
+			if (hd == 0 || hd > USHRT_MAX) {
+				what = "hd";
+				nr = hd;
+				goto unreasonable;
+			}
+			if (sec == 0 || sec > USHRT_MAX) {
+				what = "sec";
+				nr = sec;
+				goto unreasonable;
+			}
+			if (mediasize == 0)
+				warnx("unit size unknown, no sector count "
+				    "check could be done");
+			else if ((uintmax_t)(cyl + alt) * sec * hd >
+				 (uintmax_t)mediasize / sectorsize) {
+				warnx("%s, line %d: sector count %ju exceeds "
+				    "unit size %ju",
+				    file, line + 1,
+				    (uintmax_t)(cyl + alt) * sec * hd,
+				    (uintmax_t)mediasize / sectorsize);
+				fclose(fp);
+				return (1);
+			}
+			sl1.sl_pcylinders = cyl + alt;
+			sl1.sl_ncylinders = cyl;
+			sl1.sl_acylinders = alt;
+			sl1.sl_nsectors = sec;
+			sl1.sl_ntracks = hd;
+			memset(sl1.sl_text, 0, sizeof(sl1.sl_text));
+			snprintf(sl1.sl_text, sizeof(sl1.sl_text),
+			    "%s cyl %u alt %u hd %u sec %u",
+			    text, cyl, alt, hd, sec);
+			continue;
+		}
+		if (strncmp(bp, "volume name:", strlen("volume name:")) == 0) {
+			wantvtoc = 1; /* Volume name requires VTOC. */
+			bp += strlen("volume name:");
+#if SUN_VOLNAME_LEN != 8
+# error "scanf field width does not match SUN_VOLNAME_LEN"
+#endif
+			/*
+			 * We set the field length to one more than
+			 * SUN_VOLNAME_LEN to allow detecting an
+			 * overflow.
+			 */
+			memset(volname, 0, sizeof volname);
+			rv = sscanf(bp, " %9[^\n]", volname);
+			if (rv != 1) {
+				/* Clear the volume name. */
+				memset(sl1.sl_vtoc_volname, 0,
+				    SUN_VOLNAME_LEN);
+			} else {
+				memcpy(sl1.sl_vtoc_volname, volname,
+				    SUN_VOLNAME_LEN);
+				if (volname[SUN_VOLNAME_LEN] != '\0')
+					warnx(
+"%s, line %d: volume name longer than %d characters, truncating",
+					    file, line + 1, SUN_VOLNAME_LEN);
+			}
+			continue;
+		}
+		if (strlen(bp) < 2 || bp[1] != ':') {
+			line++;
+			continue;
+		}
+		rv = sscanf(bp, "%c: %30s %30s %30s %30s",
+		    &part, size, offset, tag, flag);
+		if (rv < 3) {
+		syntaxerr:
+			warnx("%s: syntax error on line %d",
+			    file, line + 1);
+			fclose(fp);
+			return (1);
+		}
+		if (parse_size(&sl1, part - 'a', size) ||
+		    parse_offset(&sl1, part - 'a', offset))
+			goto syntaxerr;
+		if (rv > 3) {
+			wantvtoc = 1;
+			if (rv == 5 && parse_flag(&sl1, part - 'a', flag))
+				goto syntaxerr;
+			if (parse_tag(&sl1, part - 'a', tag))
+				goto syntaxerr;
+		}
+		line++;
+	}
+	fclose(fp);
+	if (wantvtoc) {
+		sl1.sl_vtoc_sane = SUN_VTOC_SANE;
+		sl1.sl_vtoc_vers = SUN_VTOC_VERSION;
+		sl1.sl_vtoc_nparts = SUN_NPART;
+	} else {
+		sl1.sl_vtoc_sane = 0;
+		sl1.sl_vtoc_vers = 0;
+		sl1.sl_vtoc_nparts = 0;
+		bzero(&sl1.sl_vtoc_map, sizeof(sl1.sl_vtoc_map));
+	}
+	*sl = sl1;
+	return (check_label(sl));
+}
+
+static int
+parse_size(struct sun_disklabel *sl, int part, char *size)
+{
+	uintmax_t nsectors;
+	uintmax_t total;
+	uintmax_t n;
+	char *p;
+	int i;
+
+	nsectors = 0;
+	n = strtoumax(size, &p, 10);
+	if (*p != '\0') {
+		if (strcmp(size, "*") == 0) {
+			total = sl->sl_ncylinders * sl->sl_ntracks *
+			    sl->sl_nsectors;
+			for (i = 0; i < part; i++) {
+				if (i == 2)
+					continue;
+				nsectors += sl->sl_part[i].sdkp_nsectors;
+			}
+			n = total - nsectors;
+		} else if (p[1] == '\0' && (p[0] == 'C' || p[0] == 'c')) {
+			n = n * sl->sl_ntracks * sl->sl_nsectors;
+		} else if (p[1] == '\0' && (p[0] == 'K' || p[0] == 'k')) {
+			n = roundup((n * 1024) / 512,
+			    sl->sl_ntracks * sl->sl_nsectors);
+		} else if (p[1] == '\0' && (p[0] == 'M' || p[0] == 'm')) {
+			n = roundup((n * 1024 * 1024) / 512,
+			    sl->sl_ntracks * sl->sl_nsectors);
+		} else if (p[1] == '\0' && (p[0] == 'S' || p[0] == 's')) {
+			/* size in sectors, no action neded */
+		} else if (p[1] == '\0' && (p[0] == 'G' || p[0] == 'g')) {
+			n = roundup((n * 1024 * 1024 * 1024) / 512,
+			    sl->sl_ntracks * sl->sl_nsectors);
+		} else
+			return (-1);
+	} else if (cflag) {
+		n = n * sl->sl_ntracks * sl->sl_nsectors;
+	}
+	sl->sl_part[part].sdkp_nsectors = n;
+	return (0);
+}
+
+static int
+parse_offset(struct sun_disklabel *sl, int part, char *offset)
+{
+	uintmax_t nsectors;
+	uintmax_t n;
+	char *p;
+	int i;
+
+	nsectors = 0;
+	n = strtoumax(offset, &p, 10);
+	if (*p != '\0') {
+		if (strcmp(offset, "*") == 0) {
+			for (i = 0; i < part; i++) {
+				if (i == 2)
+					continue;
+				nsectors += sl->sl_part[i].sdkp_nsectors;
+			}
+			n = nsectors / (sl->sl_nsectors * sl->sl_ntracks);
+		} else
+			return (-1);
+	}
+	sl->sl_part[part].sdkp_cyloffset = n;
+	return (0);
+}
+
+static void
+print_label(struct sun_disklabel *sl, const char *disk, FILE *out)
+{
+	int i, j;
+	int havevtoc;
+	uintmax_t secpercyl;
+	/* Long enough to hex-encode each character. */
+	char volname[4 * SUN_VOLNAME_LEN + 1];
+
+	havevtoc = sl->sl_vtoc_sane == SUN_VTOC_SANE;
+	secpercyl = sl->sl_nsectors * sl->sl_ntracks;
+
+	fprintf(out,
+"# /dev/%s:\n"
+"text: %s\n"
+"bytes/sector: %d\n"
+"sectors/cylinder: %ju\n",
+	    disk,
+	    sl->sl_text,
+	    sectorsize,
+	    secpercyl);
+	if (eflag)
+		fprintf(out,
+		    "# max sectors/unit (including alt cylinders): %ju\n",
+		    (uintmax_t)mediasize / sectorsize);
+	fprintf(out,
+"sectors/unit: %ju\n",
+	    secpercyl * sl->sl_ncylinders);
+	if (havevtoc && sl->sl_vtoc_volname[0] != '\0') {
+		for (i = j = 0; i < SUN_VOLNAME_LEN; i++) {
+			if (sl->sl_vtoc_volname[i] == '\0')
+				break;
+			if (isprint(sl->sl_vtoc_volname[i]))
+				volname[j++] = sl->sl_vtoc_volname[i];
+			else
+				j += sprintf(volname + j, "\\x%02X",
+				    sl->sl_vtoc_volname[i]);
+		}
+		volname[j] = '\0';
+		fprintf(out, "volume name: %s\n", volname);
+	}
+	fprintf(out,
+"\n"
+"%d partitions:\n"
+"#\n",
+	    SUN_NPART);
+	if (!hflag) {
+		fprintf(out, "# Size is in %s.", cflag? "cylinders": "sectors");
+		if (eflag)
+			fprintf(out,
+"  Use %%d%c, %%dK, %%dM or %%dG to specify in %s,\n"
+"# kilobytes, megabytes or gigabytes respectively, or '*' to specify rest of\n"
+"# disk.\n",
+			    cflag? 's': 'c',
+			    cflag? "sectors": "cylinders");
+		else
+			putc('\n', out);
+		fprintf(out, "# Offset is in cylinders.");
+		if (eflag)
+			fprintf(out,
+"  Use '*' to calculate offsets automatically.\n"
+"#\n");
+		else
+			putc('\n', out);
+	}
+	if (havevtoc)
+		fprintf(out,
+"#    size       offset      tag         flag\n"
+"#    ---------- ----------  ----------  ----\n"
+			);
+	else
+		fprintf(out,
+"#    size       offset\n"
+"#    ---------- ----------\n"
+			);
+
+	for (i = 0; i < SUN_NPART; i++) {
+		if (sl->sl_part[i].sdkp_nsectors == 0)
+			continue;
+		if (hflag) {
+			fprintf(out, "  %c: %10s",
+			    'a' + i,
+			    make_h_number((uintmax_t)
+				sl->sl_part[i].sdkp_nsectors * 512));
+			fprintf(out, " %10s",
+			    make_h_number((uintmax_t)
+				sl->sl_part[i].sdkp_cyloffset * 512
+				* secpercyl));
+		} else {
+			fprintf(out, "  %c: %10ju %10u",
+			    'a' + i,
+			    sl->sl_part[i].sdkp_nsectors / (cflag? secpercyl: 1),
+			    sl->sl_part[i].sdkp_cyloffset);
+		}
+		if (havevtoc)
+			fprintf(out, " %11s %5s",
+			    tagname(sl->sl_vtoc_map[i].svtoc_tag),
+			    flagname(sl->sl_vtoc_map[i].svtoc_flag));
+		putc('\n', out);
+	}
+}
+
+static void
+usage(void)
+{
+
+	fprintf(stderr, "usage:"
+"\t%s [-r] [-c | -h] disk\n"
+"\t\t(to read label)\n"
+"\t%s -B [-b boot1] [-n] disk\n"
+"\t\t(to install boot program only)\n"
+"\t%s -R [-B [-b boot1]] [-r] [-n] [-c] disk protofile\n"
+"\t\t(to restore label)\n"
+"\t%s -e [-B [-b boot1]] [-r] [-n] [-c] disk\n"
+"\t\t(to edit label)\n"
+"\t%s -w [-B [-b boot1]] [-r] [-n] disk type\n"
+"\t\t(to write default label)\n",
+	     __progname,
+	     __progname,
+	     __progname,
+	     __progname,
+	     __progname);
+	exit(1);
+}
+
+/*
+ * Return VTOC tag and flag names for tag or flag ID, resp.
+ */
+static const char *
+tagname(unsigned int tag)
+{
+	static char buf[32];
+	size_t i;
+	struct tags *tp;
+
+	for (i = 0, tp = knowntags;
+	     i < sizeof(knowntags) / sizeof(struct tags);
+	     i++, tp++)
+		if (tp->id == tag)
+			return (tp->name);
+
+	sprintf(buf, "%u", tag);
+
+	return (buf);
+}
+
+static const char *
+flagname(unsigned int flag)
+{
+	static char buf[32];
+	size_t i;
+	struct tags *tp;
+
+	for (i = 0, tp = knownflags;
+	     i < sizeof(knownflags) / sizeof(struct tags);
+	     i++, tp++)
+		if (tp->id == flag)
+			return (tp->name);
+
+	sprintf(buf, "%u", flag);
+
+	return (buf);
+}
+
+static unsigned int
+parse_tag(struct sun_disklabel *sl, int part, const char *tag)
+{
+	struct tags *tp;
+	char *endp;
+	size_t i;
+	unsigned long l;
+
+	for (i = 0, tp = knowntags;
+	     i < sizeof(knowntags) / sizeof(struct tags);
+	     i++, tp++)
+		if (strcmp(tp->name, tag) == 0) {
+			sl->sl_vtoc_map[part].svtoc_tag = (uint16_t)tp->id;
+			return (0);
+		}
+
+	l = strtoul(tag, &endp, 0);
+	if (*tag != '\0' && *endp == '\0') {
+		sl->sl_vtoc_map[part].svtoc_tag = (uint16_t)l;
+		return (0);
+	}
+
+	return (-1);
+}
+
+static unsigned int
+parse_flag(struct sun_disklabel *sl, int part, const char *flag)
+{
+	struct tags *tp;
+	char *endp;
+	size_t i;
+	unsigned long l;
+
+	for (i = 0, tp = knownflags;
+	     i < sizeof(knownflags) / sizeof(struct tags);
+	     i++, tp++)
+		if (strcmp(tp->name, flag) == 0) {
+			sl->sl_vtoc_map[part].svtoc_flag = (uint16_t)tp->id;
+			return (0);
+		}
+
+	l = strtoul(flag, &endp, 0);
+	if (*flag != '\0' && *endp == '\0') {
+		sl->sl_vtoc_map[part].svtoc_flag = (uint16_t)l;
+		return (0);
+	}
+
+	return (-1);
+}
+
+/*
+ * Convert argument into `human readable' byte number form.
+ */
+static const char *
+make_h_number(uintmax_t u)
+{
+	static char buf[32];
+	double d;
+
+	if (u == 0) {
+		strcpy(buf, "0B");
+	} else if (u > 2000000000UL) {
+		d = (double)u / 1e9;
+		sprintf(buf, "%.1fG", d);
+	} else if (u > 2000000UL) {
+		d = (double)u / 1e6;
+		sprintf(buf, "%.1fM", d);
+	} else {
+		d = (double)u / 1e3;
+		sprintf(buf, "%.1fK", d);
+	}
+
+	return (buf);
+}


Property changes on: trunk/sbin/sunlabel/sunlabel.c
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+MidnightBSD=%H
\ No newline at end of property
Added: svn:mime-type
## -0,0 +1 ##
+text/plain
\ No newline at end of property


More information about the Midnightbsd-cvs mailing list