diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/kern/subr_disk.c | 78 | ||||
-rw-r--r-- | sys/sys/disk.h | 8 |
2 files changed, 81 insertions, 5 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; +} diff --git a/sys/sys/disk.h b/sys/sys/disk.h index 9005ace6f7f..aac95492946 100644 --- a/sys/sys/disk.h +++ b/sys/sys/disk.h @@ -1,4 +1,4 @@ -/* $OpenBSD: disk.h,v 1.20 2009/06/17 01:30:32 thib Exp $ */ +/* $OpenBSD: disk.h,v 1.21 2010/05/03 15:27:28 jsing Exp $ */ /* $NetBSD: disk.h,v 1.11 1996/04/28 20:22:50 thorpej Exp $ */ /* @@ -132,6 +132,10 @@ struct dkdriver { #define DK_OPEN 4 /* label read, drive open */ #define DK_OPENRAW 5 /* open without label */ +/* Disk map flags. */ +#define DM_OPENPART 0x1 /* Open raw partition. */ +#define DM_OPENBLCK 0x2 /* Open block device. */ + #ifdef DISKSORT_STATS /* * Stats from disksort(). @@ -165,4 +169,6 @@ void disk_unbusy(struct disk *, long, int); int disk_lock(struct disk *); void disk_unlock(struct disk *); + +int disk_map(char *, char *, int, int); #endif |