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_ */