Module Name:    src
Committed By:   brad
Date:           Thu Aug 22 20:23:43 UTC 2019

Modified Files:
        src/lib/libutil: getdiskrawname.c

Log Message:
Teach getdiskrawname and getdiskcookedname about zvols.

Reviewed by Christos


To generate a diff of this commit:
cvs rdiff -u -r1.5 -r1.6 src/lib/libutil/getdiskrawname.c

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

Modified files:

Index: src/lib/libutil/getdiskrawname.c
diff -u src/lib/libutil/getdiskrawname.c:1.5 src/lib/libutil/getdiskrawname.c:1.6
--- src/lib/libutil/getdiskrawname.c:1.5	Wed Sep 17 23:54:42 2014
+++ src/lib/libutil/getdiskrawname.c	Thu Aug 22 20:23:43 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: getdiskrawname.c,v 1.5 2014/09/17 23:54:42 christos Exp $	*/
+/*	$NetBSD: getdiskrawname.c,v 1.6 2019/08/22 20:23:43 brad Exp $	*/
 
 /*-
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
@@ -29,7 +29,7 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: getdiskrawname.c,v 1.5 2014/09/17 23:54:42 christos Exp $");
+__RCSID("$NetBSD: getdiskrawname.c,v 1.6 2019/08/22 20:23:43 brad Exp $");
 
 #include <sys/stat.h>
 
@@ -70,10 +70,74 @@ resolve_link(char *buf, size_t bufsiz, c
 	return buf;
 }
 
+/*
+ * zvol device names look like:
+ * /dev/zvol/dsk/pool_name/.../volume_name
+ * /dev/zvol/rdsk/pool_name/.../volume_name
+ *
+ * ZFS pools can be divided nearly to infinity
+ *
+ * This allows for 16 pool names, which one would hope would be enough
+ */
+#define DISKMAXPARTS 20
+static int
+calc_zvol_name(char *buf, size_t bufsiz, const char *name, const char *raw)
+{
+	char copyname[PATH_MAX];
+	char *names[DISKMAXPARTS];
+	char *last, *p;
+	size_t i = 0;
+
+	strlcpy(copyname, name, sizeof(copyname));
+	for (p = strtok_r(copyname, "/", &last); p;
+	     p = strtok_r(NULL, "/", &last)) {
+		if (i >= DISKMAXPARTS) {
+			errno =  ENOSPC;
+			return -1;
+		}
+		names[i++] = p;
+	}
+
+	if (i < 4) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	snprintf(buf, bufsiz, "/dev/zvol/%sdsk", raw);
+	for (size_t j = 3; j < i; j++) {
+		strlcat(buf, "/", bufsiz);
+		strlcat(buf, names[j], bufsiz);
+	}
+	return 0;
+}
+
+static int
+calc_name(char *buf, size_t bufsiz, const char *name, const char *raw)
+{
+	int skip = 1;
+
+	if (strncmp("/dev/zvol/", name, 10) == 0)
+		return calc_zvol_name(buf, bufsiz, name, raw);
+
+	const char *dp = strrchr(name, '/');
+	if (!*raw && ((dp != NULL && dp[1] != 'r')
+		|| (dp == NULL && name[0] != 'r'))) {
+		errno = EINVAL;
+		return -1;
+	}
+	if (raw[0] != 'r')
+		skip = 2;
+	if (dp != NULL)
+		snprintf(buf, bufsiz, "%.*s/%s%s", (int)(dp - name),
+		    name, raw, dp + skip);
+	else
+		snprintf(buf, bufsiz, "%s%s", raw, name);
+	return 0;
+}
+
 const char *
 getdiskrawname(char *buf, size_t bufsiz, const char *name)
 {
-	const char *dp;
 	struct stat st;
 	char dest[PATH_MAX];
 
@@ -82,8 +146,6 @@ getdiskrawname(char *buf, size_t bufsiz,
 		return NULL;
 	}
 
-	dp = strrchr(name, '/');
-
 	if (stat(name, &st) == -1)
 		return NULL;
 
@@ -92,10 +154,8 @@ getdiskrawname(char *buf, size_t bufsiz,
 		return NULL;
 	}
 
-	if (dp != NULL)
-		(void)snprintf(buf, bufsiz, "%.*s/r%s", (int)(dp - name), name, dp + 1);
-	else
-		(void)snprintf(buf, bufsiz, "r%s", name);
+	if (calc_name(buf, bufsiz, name, "r") == -1)
+		return NULL;
 
 	return buf;
 }
@@ -103,7 +163,6 @@ getdiskrawname(char *buf, size_t bufsiz,
 const char *
 getdiskcookedname(char *buf, size_t bufsiz, const char *name)
 {
-	const char *dp;
 	struct stat st;
 	char dest[PATH_MAX];
 
@@ -112,13 +171,6 @@ getdiskcookedname(char *buf, size_t bufs
 		return NULL;
 	}
 
-	dp = strrchr(name, '/');
-
-	if ((dp != NULL && dp[1] != 'r') || (dp == NULL && name[0] != 'r')) {
-		errno = EINVAL;
-		return NULL;
-	}
-
 	if (stat(name, &st) == -1)
 		return NULL;
 
@@ -127,10 +179,8 @@ getdiskcookedname(char *buf, size_t bufs
 		return NULL;
 	}
 
-	if (dp != NULL)
-		(void)snprintf(buf, bufsiz, "%.*s/%s", (int)(dp - name), name, dp + 2);
-	else
-		(void)snprintf(buf, bufsiz, "%s", name + 1);
+	if (calc_name(buf, bufsiz, name, "") == -1)
+		return NULL;
 
 	return buf;
 }

Reply via email to