summaryrefslogtreecommitdiffstats
path: root/sys/kern/subr_disk.c
diff options
context:
space:
mode:
authorjsing <jsing@openbsd.org>2010-05-03 15:27:28 +0000
committerjsing <jsing@openbsd.org>2010-05-03 15:27:28 +0000
commit52a4d5b43603bb71ac086cc24eeb64d602f6a63f (patch)
treeb3754d568fd145685e45452fe402764829851291 /sys/kern/subr_disk.c
parentSwitch newfs to opendev(3) - this simplies the code and will allow it to (diff)
downloadwireguard-openbsd-52a4d5b43603bb71ac086cc24eeb64d602f6a63f.tar.xz
wireguard-openbsd-52a4d5b43603bb71ac086cc24eeb64d602f6a63f.zip
Provide a disk_map() function which attempts to map a disklabel UID to the
actual device. If successful, the real path is returned via mappath. Soon to be used by several other diffs. ok krw@
Diffstat (limited to 'sys/kern/subr_disk.c')
-rw-r--r--sys/kern/subr_disk.c78
1 files changed, 74 insertions, 4 deletions
diff --git a/sys/kern/subr_disk.c b/sys/kern/subr_disk.c
index 8c66be4bcb0..a91a5a26636 100644
--- a/sys/kern/subr_disk.c
+++ b/sys/kern/subr_disk.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: subr_disk.c,v 1.102 2010/04/28 12:54:04 jsing Exp $ */
+/* $OpenBSD: subr_disk.c,v 1.103 2010/05/03 15:27:28 jsing Exp $ */
/* $NetBSD: subr_disk.c,v 1.17 1996/03/16 23:17:08 christos Exp $ */
/*
@@ -602,14 +602,13 @@ notfat:
}
/*
- * Check new disk label for sensibility
- * before setting it.
+ * Check new disk label for sensibility before setting it.
*/
int
setdisklabel(struct disklabel *olp, struct disklabel *nlp, u_int openmask)
{
struct partition *opp, *npp;
- struct disk *dk = NULL;
+ struct disk *dk;
u_int64_t uid;
int i;
@@ -1283,3 +1282,74 @@ findblkname(int maj)
return (nam2blk[i].name);
return (NULL);
}
+
+int
+disk_map(char *path, char *mappath, int size, int flags)
+{
+ struct disk *dk, *mdk;
+ u_char uid[8];
+ char c, part;
+ int i;
+
+ /*
+ * Attempt to map a request for a disklabel UID to the correct device.
+ * We should be supplied with a disklabel UID which has the following
+ * format:
+ *
+ * [disklabel uid] . [partition]
+ *
+ * Alternatively, if the DM_OPENPART flag is set the disklabel UID can
+ * based passed on its own.
+ */
+
+ if (strchr(path, '/') != NULL)
+ return -1;
+
+ /* Verify that the device name is properly formed. */
+ if (!((strlen(path) == 16 && (flags & DM_OPENPART)) ||
+ (strlen(path) == 18 && path[16] == '.')))
+ return -1;
+
+ /* Get partition. */
+ if (flags & DM_OPENPART)
+ part = 'a' + RAW_PART;
+ else
+ part = path[17];
+
+ if (part < 'a' || part >= 'a' + MAXPARTITIONS)
+ return -1;
+
+ /* Derive label UID. */
+ bzero(uid, sizeof(uid));
+ for (i = 0; i < 16; i++) {
+ c = path[i];
+ if (c >= '0' && c <= '9')
+ c -= '0';
+ else if (c >= 'a' && c <= 'f')
+ c -= ('a' - 10);
+ else
+ return -1;
+
+ uid[i / 2] <<= 4;
+ uid[i / 2] |= c & 0xf;
+ }
+
+ mdk = NULL;
+ TAILQ_FOREACH(dk, &disklist, dk_link) {
+ if (dk->dk_label && bcmp(dk->dk_label->d_uid, uid,
+ sizeof(dk->dk_label->d_uid)) == 0) {
+ /* Fail if there are duplicate UIDs! */
+ if (mdk != NULL)
+ return -1;
+ mdk = dk;
+ }
+ }
+
+ if (mdk == NULL || mdk->dk_name == NULL)
+ return -1;
+
+ snprintf(mappath, size, "/dev/%s%s%c",
+ (flags & DM_OPENBLCK) ? "" : "r", mdk->dk_name, part);
+
+ return 0;
+}