[PATCH v6 1/4] lib: new helper kstrtodev_t()

From: Uwe Kleine-KÃnig
Date: Thu Feb 13 2020 - 04:25:02 EST


This function is in the same spirit as the other kstrto* functions and
uses the same calling convention. It expects the input string to be in
the format %u:%u and implements stricter parsing than sscanf as it
returns an error on trailing data (other than the usual \n).

Signed-off-by: Uwe Kleine-KÃnig <uwe@xxxxxxxxxxxxxxxxx>
---
include/linux/kdev_t.h | 2 ++
include/linux/kernel.h | 1 +
lib/kstrtox.c | 46 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 49 insertions(+)

diff --git a/include/linux/kdev_t.h b/include/linux/kdev_t.h
index 85b5151911cf..3a5c24bd8fa4 100644
--- a/include/linux/kdev_t.h
+++ b/include/linux/kdev_t.h
@@ -4,8 +4,10 @@

#include <uapi/linux/kdev_t.h>

+/* dev_t is 32 bit wide, 20 bits are used for MINOR, 12 for major */
#define MINORBITS 20
#define MINORMASK ((1U << MINORBITS) - 1)
+#define MAJORBITS 12

#define MAJOR(dev) ((unsigned int) ((dev) >> MINORBITS))
#define MINOR(dev) ((unsigned int) ((dev) & MINORMASK))
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 0d9db2a14f44..9cf694c5d2c3 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -410,6 +410,7 @@ int __must_check kstrtos16(const char *s, unsigned int base, s16 *res);
int __must_check kstrtou8(const char *s, unsigned int base, u8 *res);
int __must_check kstrtos8(const char *s, unsigned int base, s8 *res);
int __must_check kstrtobool(const char *s, bool *res);
+int __must_check kstrtodev_t(const char *s, dev_t *res);

int __must_check kstrtoull_from_user(const char __user *s, size_t count, unsigned int base, unsigned long long *res);
int __must_check kstrtoll_from_user(const char __user *s, size_t count, unsigned int base, long long *res);
diff --git a/lib/kstrtox.c b/lib/kstrtox.c
index 1006bf70bf74..e1b896635c6a 100644
--- a/lib/kstrtox.c
+++ b/lib/kstrtox.c
@@ -19,6 +19,7 @@
#include <linux/export.h>
#include <linux/types.h>
#include <linux/uaccess.h>
+#include <linux/kdev_t.h>
#include "kstrtox.h"

const char *_parse_integer_fixup_radix(const char *s, unsigned int *base)
@@ -367,6 +368,51 @@ int kstrtobool(const char *s, bool *res)
}
EXPORT_SYMBOL(kstrtobool);

+/**
+ * kstrtodev_t - convert a string in format %u:%u to a dev_t
+ * @s: input string
+ * @res: result
+ *
+ * This is the reverse of print_dev_t. The first number is interpreted as major,
+ * the second as minor.
+ */
+int kstrtodev_t(const char *s, dev_t *res)
+{
+ unsigned long long _res;
+ unsigned int ma, mi;
+ int rv;
+
+ rv = _parse_integer(s, 10, &_res);
+ if (rv < 0)
+ return rv;
+ if (rv & KSTRTOX_OVERFLOW || _res >= (1U << MAJORBITS))
+ return -ERANGE;
+ ma = _res;
+
+ s += rv;
+
+ if (*s++ != ':')
+ return -EINVAL;
+
+ rv = _parse_integer(s, 10, &_res);
+ if (rv < 0)
+ return rv;
+ if (rv & KSTRTOX_OVERFLOW || _res >= (1U << MINORBITS))
+ return -ERANGE;
+ mi = _res;
+
+ s += rv;
+
+ if (*s == '\n')
+ s++;
+ if (*s)
+ return -EINVAL;
+
+ *res = MKDEV(ma, mi);
+ return 0;
+}
+EXPORT_SYMBOL(kstrtodev_t);
+
/*
* Since "base" would be a nonsense argument, this open-codes the
* _from_user helper instead of using the helper macro below.
--
2.24.0