Module Name:    src
Committed By:   pooka
Date:           Wed Oct  7 20:51:00 UTC 2009

Modified Files:
        src/lib/libukfs: Makefile ukfs.c ukfs.h
Added Files:
        src/lib/libukfs: ukfs_disklabel.c ukfs_int_disklabel.h

Log Message:
Add what is essentially disklabel support.  All disk-based file
systems should be mounted with ukfs_mount_disk() from now on.  The
partition argument specifies which label is being mounted (or the
entire image).  E.g. partition 4 should be label 'e'.


To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.3 src/lib/libukfs/Makefile
cvs rdiff -u -r1.37 -r1.38 src/lib/libukfs/ukfs.c
cvs rdiff -u -r1.10 -r1.11 src/lib/libukfs/ukfs.h
cvs rdiff -u -r0 -r1.1 src/lib/libukfs/ukfs_disklabel.c \
    src/lib/libukfs/ukfs_int_disklabel.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/lib/libukfs/Makefile
diff -u src/lib/libukfs/Makefile:1.2 src/lib/libukfs/Makefile:1.3
--- src/lib/libukfs/Makefile:1.2	Thu Nov 27 16:14:46 2008
+++ src/lib/libukfs/Makefile	Wed Oct  7 20:51:00 2009
@@ -1,14 +1,15 @@
-#	$NetBSD: Makefile,v 1.2 2008/11/27 16:14:46 pooka Exp $
+#	$NetBSD: Makefile,v 1.3 2009/10/07 20:51:00 pooka Exp $
 #
 
 LIB=		ukfs
 LIBDPLIBS+=	rump	${.CURDIR}/../librump		\
 		rumpvfs	${.CURDIR}/../librumpvfs
+CPPFLAGS+=	-I${.CURDIR}
 
 INCS=		ukfs.h
 INCSDIR=	/usr/include/rump
 
-SRCS=		ukfs.c
+SRCS=		ukfs.c ukfs_disklabel.c
 MAN=		ukfs.3
 
 .include <bsd.lib.mk>

Index: src/lib/libukfs/ukfs.c
diff -u src/lib/libukfs/ukfs.c:1.37 src/lib/libukfs/ukfs.c:1.38
--- src/lib/libukfs/ukfs.c:1.37	Fri Oct  2 09:32:01 2009
+++ src/lib/libukfs/ukfs.c	Wed Oct  7 20:51:00 2009
@@ -1,7 +1,7 @@
-/*	$NetBSD: ukfs.c,v 1.37 2009/10/02 09:32:01 pooka Exp $	*/
+/*	$NetBSD: ukfs.c,v 1.38 2009/10/07 20:51:00 pooka Exp $	*/
 
 /*
- * Copyright (c) 2007, 2008  Antti Kantee.  All Rights Reserved.
+ * Copyright (c) 2007, 2008, 2009  Antti Kantee.  All Rights Reserved.
  *
  * Development of this software was supported by the
  * Finnish Cultural Foundation.
@@ -63,6 +63,8 @@
 #include <rump/rump.h>
 #include <rump/rump_syscalls.h>
 
+#include "ukfs_int_disklabel.h"
+
 #define UKFS_MODE_DEFAULT 0555
 
 struct ukfs {
@@ -187,63 +189,149 @@
 	return rump_sys_mkdir(path, mode);
 }
 
-struct ukfs *
-ukfs_mount(const char *vfsname, const char *devpath, const char *mountpath,
-	int mntflags, void *arg, size_t alen)
+int
+ukfs_partition_probe(char *devpath, int *partition)
 {
-	struct stat sb;
-	struct ukfs *fs = NULL;
-	int rv = 0, devfd = -1, rdonly;
-	int mounted = 0;
-	int regged = 0;
-	int doreg = 0;
+	char *p;
+	int rv = 0;
 
 	/*
-	 * Try open and lock the device.  if we can't open it, assume
-	 * it's a file system which doesn't use a real device and let
-	 * it slide.  The mount will fail anyway if the fs requires a
-	 * device.
-	 *
-	 * XXX: strictly speaking this is not 100% correct, as virtual
-	 * file systems can use a device path which does exist and can
-	 * be opened.  E.g. tmpfs should be mountable multiple times
-	 * with "device" path "/swap", but now isn't.  But I think the
-	 * chances are so low that it's currently acceptable to let
-	 * this one slip.
+	 * Check for disklabel magic in pathname:
+	 * /regularpath%PART:<char>%\0
 	 */
-	rdonly = mntflags & MNT_RDONLY;
+#define MAGICADJ(p, n) (p+sizeof(UKFS_PARTITION_SCANMAGIC)-1+n)
+	if ((p = strstr(devpath, UKFS_PARTITION_SCANMAGIC)) != NULL
+	    && strlen(p) == UKFS_PARTITION_MAGICLEN
+	    && *(MAGICADJ(p,1)) == '%') {
+		if (*(MAGICADJ(p,0)) >= 'a' &&
+		    *(MAGICADJ(p,0)) < 'a' + UKFS_MAXPARTITIONS) {
+			*partition = *(MAGICADJ(p,0)) - 'a';
+			*p = '\0';
+		} else {
+			rv = EINVAL;
+		}
+	} else {
+		*partition = UKFS_PARTITION_NONE;
+	}
+
+	return rv;
+}
+
+/*
+ * Open the disk file and flock it.  Also, if we are operation on
+ * an embedded partition, find the partition offset and size from
+ * the disklabel.
+ *
+ * We hard-fail only in two cases:
+ *  1) we failed to get the partition info out (don't know what offset
+ *     to mount from)
+ *  2) we failed to flock the source device (i.e. flock() fails,
+ *     not e.g. open() before it)
+ *
+ * Otherwise we let the code proceed to mount and let the file system
+ * throw the proper error.  The only questionable bit is that if we
+ * soft-fail before flock() and mount does succeed...
+ *
+ * Returns: -1 error (errno reports error code)
+ *           0 success
+ *
+ * dfdp: -1  device is not open
+ *        n  device is open
+ */
+static int
+process_diskdevice(const char *devpath, int partition, int rdonly,
+	int *dfdp, uint64_t *devoff, uint64_t *devsize)
+{
+	char buf[65536];
+	struct stat sb;
+	struct ukfs_disklabel dl;
+	struct ukfs_partition *pp;
+	int rv = 0, devfd;
+
+	/* defaults */
+	*devoff = 0;
+	*devsize = RUMP_ETFS_SIZE_ENDOFF;
+	*dfdp = -1;
+
 	devfd = open(devpath, rdonly ? O_RDONLY : O_RDWR);
-	if (devfd != -1) {
-		if (fstat(devfd, &sb) == -1) {
-			close(devfd);
-			devfd = -1;
+	if (devfd == -1) {
+		if (UKFS_USEPARTITION(partition))
+			rv = errno;
+		goto out;
+	}
+
+	/*
+	 * Locate the disklabel and find the partition in question.
+	 */
+	if (UKFS_USEPARTITION(partition)) {
+		if (pread(devfd, buf, sizeof(buf), 0) == -1) {
 			rv = errno;
 			goto out;
 		}
 
-		/*
-		 * We do this only for non-block device since the
-		 * (NetBSD) kernel allows block device open only once.
-		 */
-		if (!S_ISBLK(sb.st_mode)) {
-			if (flock(devfd, LOCK_NB | (rdonly ? LOCK_SH:LOCK_EX))
-			    == -1) {
-				warnx("ukfs_mount: cannot get %s lock on "
-				    "device", rdonly ? "shared" : "exclusive");
-				close(devfd);
-				devfd = -1;
-				rv = errno;
-				goto out;
-			}
-		} else {
-			close(devfd);
-			devfd = -1;
+		if (ukfs_disklabel_scan(&dl, buf, sizeof(buf)) != 0) {
+			rv = ENOENT;
+			goto out;
 		}
-		doreg = 1;
-	} else if (errno != ENOENT) {
-		doreg = 1;
+
+		if (dl.d_npartitions < partition) {
+			rv = ENOENT;
+			goto out;
+		}
+
+		pp = &dl.d_partitions[partition];
+		*devoff = pp->p_offset << DEV_BSHIFT;
+		*devsize = pp->p_size << DEV_BSHIFT;
 	}
 
+	if (fstat(devfd, &sb) == -1) {
+		rv = errno;
+		goto out;
+	}
+
+	/*
+	 * We do this only for non-block device since the
+	 * (NetBSD) kernel allows block device open only once.
+	 * We also need to close the device for fairly obvious reasons.
+	 */
+	if (!S_ISBLK(sb.st_mode)) {
+		if (flock(devfd, LOCK_NB | (rdonly ? LOCK_SH:LOCK_EX)) == -1) {
+			warnx("ukfs_mount: cannot get %s lock on "
+			    "device", rdonly ? "shared" : "exclusive");
+			rv = errno;
+			goto out;
+		}
+	} else {
+		close(devfd);
+		devfd = -1;
+	}
+	*dfdp = devfd;
+
+ out:
+	if (rv) {
+		if (devfd != -1)
+			close(devfd);
+		errno = rv;
+		rv = -1;
+	}
+
+	return rv;
+}
+
+static struct ukfs *
+doukfsmount(const char *vfsname, const char *devpath, int partition,
+	const char *mountpath, int mntflags, void *arg, size_t alen)
+{
+	struct ukfs *fs = NULL;
+	int rv = 0, devfd;
+	uint64_t devoff, devsize;
+	int mounted = 0;
+	int regged = 0;
+
+	if (partition != UKFS_PARTITION_NA)
+		process_diskdevice(devpath, partition, mntflags & MNT_RDONLY,
+		    &devfd, &devoff, &devsize);
+
 	fs = malloc(sizeof(struct ukfs));
 	if (fs == NULL) {
 		rv = ENOMEM;
@@ -259,13 +347,15 @@
 		}
 	}
 
-	if (doreg) {
-		rv = rump_etfs_register(devpath, devpath, RUMP_ETFS_BLK);
+	if (partition != UKFS_PARTITION_NA) {
+		rv = rump_etfs_register_withsize(devpath, devpath,
+		    RUMP_ETFS_BLK, devoff, devsize);
 		if (rv) {
 			goto out;
 		}
 		regged = 1;
 	}
+
 	rv = rump_sys_mount(vfsname, mountpath, mntflags, arg, alen);
 	if (rv) {
 		rv = errno;
@@ -312,6 +402,24 @@
 	return fs;
 }
 
+struct ukfs *
+ukfs_mount(const char *vfsname, const char *devpath,
+	const char *mountpath, int mntflags, void *arg, size_t alen)
+{
+
+	return doukfsmount(vfsname, devpath, UKFS_PARTITION_NA,
+	    mountpath, mntflags, arg, alen);
+}
+
+struct ukfs *
+ukfs_mount_disk(const char *vfsname, const char *devpath, int partition,
+	const char *mountpath, int mntflags, void *arg, size_t alen)
+{
+
+	return doukfsmount(vfsname, devpath, partition,
+	    mountpath, mntflags, arg, alen);
+}
+
 int
 ukfs_release(struct ukfs *fs, int flags)
 {

Index: src/lib/libukfs/ukfs.h
diff -u src/lib/libukfs/ukfs.h:1.10 src/lib/libukfs/ukfs.h:1.11
--- src/lib/libukfs/ukfs.h:1.10	Fri Oct  2 09:32:01 2009
+++ src/lib/libukfs/ukfs.h	Wed Oct  7 20:51:00 2009
@@ -1,7 +1,7 @@
-/*	$NetBSD: ukfs.h,v 1.10 2009/10/02 09:32:01 pooka Exp $	*/
+/*	$NetBSD: ukfs.h,v 1.11 2009/10/07 20:51:00 pooka Exp $	*/
 
 /*
- * Copyright (c) 2007, 2008  Antti Kantee.  All Rights Reserved.
+ * Copyright (c) 2007, 2008, 2009  Antti Kantee.  All Rights Reserved.
  *
  * Development of this software was supported by the
  * Finnish Cultural Foundation.
@@ -55,7 +55,9 @@
 
 int		_ukfs_init(int);
 struct ukfs	*ukfs_mount(const char *, const char *, const char *,
-			  int, void *, size_t);
+			    int, void *, size_t);
+struct ukfs	*ukfs_mount_disk(const char *, const char *, int,
+				 const char *, int, void *, size_t);
 int		ukfs_release(struct ukfs *, int);
 
 int		ukfs_opendir(struct ukfs *, const char *,
@@ -111,6 +113,22 @@
 void		ukfs_setspecific(struct ukfs *, void *);
 void *		ukfs_getspecific(struct ukfs *);
 
+/* partition magic in device names */
+#define UKFS_PARTITION_SCANMAGIC "%PART:"
+#define UKFS_PARTITION_MAGICLEN (sizeof(UKFS_PARTITION_SCANMAGIC "a%")-1)
+#define UKFS_PARTITION_MAXPATHLEN (MAXPATHLEN+UKFS_PARTITION_MAGICLEN)
+#define UKFS_PARTITION_NONE (-1)
+#define UKFS_PARTITION_NA (-2)
+#define UKFS_USEPARTITION(a)						\
+	((a) != UKFS_PARTITION_NONE && (a) != UKFS_PARTITION_NA)
+#define UKFS_PARTITION_ARGVPROBE(part)					\
+do {									\
+	if (argc >= 3)							\
+		ukfs_partition_probe(argv[argc-2], &part);		\
+} while (/*CONSTCOND*/0)
+
+int		ukfs_partition_probe(char *, int *);
+
 /* dynamic loading of library modules */
 int		ukfs_modload(const char *);
 int		ukfs_modload_dir(const char *);

Added files:

Index: src/lib/libukfs/ukfs_disklabel.c
diff -u /dev/null src/lib/libukfs/ukfs_disklabel.c:1.1
--- /dev/null	Wed Oct  7 20:51:00 2009
+++ src/lib/libukfs/ukfs_disklabel.c	Wed Oct  7 20:51:00 2009
@@ -0,0 +1,124 @@
+/*	$NetBSD: ukfs_disklabel.c,v 1.1 2009/10/07 20:51:00 pooka Exp $	*/
+
+/*
+ * Local copies of libutil disklabel routines.  This uncouples libukfs
+ * from the NetBSD-only libutil.  All identifiers are prefixed with
+ * ukfs or UKFS, otherwise the routines are the same.
+ */
+
+/*
+ * From:
+ * NetBSD: disklabel_scan.c,v 1.3 2009/01/18 12:13:03 lukem Exp
+ */
+
+/*-
+ * Copyright (c) 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Roland C. Dowdeswell.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#include <sys/types.h>
+
+#include <string.h>
+#include <unistd.h>
+
+#include "ukfs_int_disklabel.h"
+
+#define SCAN_INCR	4
+
+int
+ukfs_disklabel_scan(struct ukfs_disklabel *lp, char *buf, size_t buflen)
+{
+	size_t	i;
+
+	/* scan for the correct magic numbers. */
+
+	for (i=0; i <= buflen - sizeof(*lp); i += SCAN_INCR) {
+		memcpy(lp, buf + i, sizeof(*lp));
+		if (lp->d_magic == UKFS_DISKMAGIC &&
+		    lp->d_magic2 == UKFS_DISKMAGIC)
+			goto sanity;
+	}
+
+	return 1;
+
+sanity:
+	/* we've found something, let's sanity check it */
+	if (lp->d_npartitions > UKFS_MAXPARTITIONS
+	    || ukfs_disklabel_dkcksum(lp))
+		return 1;
+
+	return 0;
+}
+
+
+/*
+ * From:
+ *	$NetBSD: disklabel_dkcksum.c,v 1.4 2005/05/15 21:01:34 thorpej Exp
+ */
+
+/*-
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. 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.
+ */
+
+uint16_t
+ukfs_disklabel_dkcksum(struct ukfs_disklabel *lp)
+{
+	uint16_t *start, *end;
+	uint16_t sum;
+
+	sum = 0;
+	start = (uint16_t *)(void *)lp;
+	end = (uint16_t *)(void *)&lp->d_partitions[lp->d_npartitions];
+	while (start < end)
+		sum ^= *start++;
+	return (sum);
+}
Index: src/lib/libukfs/ukfs_int_disklabel.h
diff -u /dev/null src/lib/libukfs/ukfs_int_disklabel.h:1.1
--- /dev/null	Wed Oct  7 20:51:00 2009
+++ src/lib/libukfs/ukfs_int_disklabel.h	Wed Oct  7 20:51:00 2009
@@ -0,0 +1,157 @@
+/*	$NetBSD: ukfs_int_disklabel.h,v 1.1 2009/10/07 20:51:00 pooka Exp $	*/
+
+/*
+ * Modified copy of disklabel.h so that ukfs doesn't have to depend
+ * on NetBSD headers.  Contains just about only "struct disklabel".
+ * The on-disk disklabel doesn't really change format, so no need
+ * to track this against NetBSD changes.
+ */
+
+/*
+ * Copyright (c) 1987, 1988, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)disklabel.h	8.2 (Berkeley) 7/10/94
+ */
+
+#ifndef LIB_UKFS_DISKLABEL_H_
+#define	LIB_UKFS_DISKLABEL_H_
+
+#include <sys/types.h>
+
+#include <stdint.h>
+
+#define	UKFS_MAXPARTITIONS	22
+#define	UKFS_DISKMAGIC	((uint32_t)0x82564557)	/* The disk magic number */
+
+struct ukfs_disklabel {
+	uint32_t d_magic;		/* the magic number */
+	uint16_t d_type;		/* drive type */
+	uint16_t d_subtype;		/* controller/d_type specific */
+	char	  d_typename[16];	/* type name, e.g. "eagle" */
+
+	/*
+	 * d_packname contains the pack identifier and is returned when
+	 * the disklabel is read off the disk or in-core copy.
+	 * d_boot0 and d_boot1 are the (optional) names of the
+	 * primary (block 0) and secondary (block 1-15) bootstraps
+	 * as found in /usr/mdec.  These are returned when using
+	 * getdiskbyname(3) to retrieve the values from /etc/disktab.
+	 */
+	union {
+		char	un_d_packname[16];	/* pack identifier */
+		struct {
+			char *un_d_boot0;	/* primary bootstrap name */
+			char *un_d_boot1;	/* secondary bootstrap name */
+		} un_b;
+	} d_un;
+#define	d_packname	d_un.un_d_packname
+#define	d_boot0		d_un.un_b.un_d_boot0
+#define	d_boot1		d_un.un_b.un_d_boot1
+
+			/* disk geometry: */
+	uint32_t d_secsize;		/* # of bytes per sector */
+	uint32_t d_nsectors;		/* # of data sectors per track */
+	uint32_t d_ntracks;		/* # of tracks per cylinder */
+	uint32_t d_ncylinders;		/* # of data cylinders per unit */
+	uint32_t d_secpercyl;		/* # of data sectors per cylinder */
+	uint32_t d_secperunit;		/* # of data sectors per unit */
+
+	/*
+	 * Spares (bad sector replacements) below are not counted in
+	 * d_nsectors or d_secpercyl.  Spare sectors are assumed to
+	 * be physical sectors which occupy space at the end of each
+	 * track and/or cylinder.
+	 */
+	uint16_t d_sparespertrack;	/* # of spare sectors per track */
+	uint16_t d_sparespercyl;	/* # of spare sectors per cylinder */
+	/*
+	 * Alternative cylinders include maintenance, replacement,
+	 * configuration description areas, etc.
+	 */
+	uint32_t d_acylinders;		/* # of alt. cylinders per unit */
+
+			/* hardware characteristics: */
+	/*
+	 * d_interleave, d_trackskew and d_cylskew describe perturbations
+	 * in the media format used to compensate for a slow controller.
+	 * Interleave is physical sector interleave, set up by the
+	 * formatter or controller when formatting.  When interleaving is
+	 * in use, logically adjacent sectors are not physically
+	 * contiguous, but instead are separated by some number of
+	 * sectors.  It is specified as the ratio of physical sectors
+	 * traversed per logical sector.  Thus an interleave of 1:1
+	 * implies contiguous layout, while 2:1 implies that logical
+	 * sector 0 is separated by one sector from logical sector 1.
+	 * d_trackskew is the offset of sector 0 on track N relative to
+	 * sector 0 on track N-1 on the same cylinder.  Finally, d_cylskew
+	 * is the offset of sector 0 on cylinder N relative to sector 0
+	 * on cylinder N-1.
+	 */
+	uint16_t d_rpm;		/* rotational speed */
+	uint16_t d_interleave;		/* hardware sector interleave */
+	uint16_t d_trackskew;		/* sector 0 skew, per track */
+	uint16_t d_cylskew;		/* sector 0 skew, per cylinder */
+	uint32_t d_headswitch;		/* head switch time, usec */
+	uint32_t d_trkseek;		/* track-to-track seek, usec */
+	uint32_t d_flags;		/* generic flags */
+#define	NDDATA 5
+	uint32_t d_drivedata[NDDATA];	/* drive-type specific information */
+#define	NSPARE 5
+	uint32_t d_spare[NSPARE];	/* reserved for future use */
+	uint32_t d_magic2;		/* the magic number (again) */
+	uint16_t d_checksum;		/* xor of data incl. partitions */
+
+			/* filesystem and partition information: */
+	uint16_t d_npartitions;	/* number of partitions in following */
+	uint32_t d_bbsize;		/* size of boot area at sn0, bytes */
+	uint32_t d_sbsize;		/* max size of fs superblock, bytes */
+	struct	ukfs_partition {	/* the partition table */
+		uint32_t p_size;	/* number of sectors in partition */
+		uint32_t p_offset;	/* starting sector */
+		union {
+			uint32_t fsize; /* FFS, ADOS:
+					    filesystem basic fragment size */
+			uint32_t cdsession; /* ISO9660: session offset */
+		} __partition_u2;
+#define	p_fsize		__partition_u2.fsize
+#define	p_cdsession	__partition_u2.cdsession
+		uint8_t p_fstype;	/* filesystem type, see below */
+		uint8_t p_frag;	/* filesystem fragments per block */
+		union {
+			uint16_t cpg;	/* UFS: FS cylinders per group */
+			uint16_t sgs;	/* LFS: FS segment shift */
+		} __partition_u1;
+#define	p_cpg	__partition_u1.cpg
+#define	p_sgs	__partition_u1.sgs
+	} d_partitions[UKFS_MAXPARTITIONS];	/* actually may be more */
+};
+
+uint16_t        ukfs_disklabel_dkcksum(struct ukfs_disklabel *);
+int             ukfs_disklabel_scan(struct ukfs_disklabel *, char *, size_t);
+
+#endif /* !LIB_UKFS_DISKLABEL_H_ */

Reply via email to