[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20200213091600.554-2-uwe@kleine-koenig.org>
Date: Thu, 13 Feb 2020 10:15:57 +0100
From: Uwe Kleine-König <uwe@...ine-koenig.org>
To: Jacek Anaszewski <jacek.anaszewski@...il.com>,
Pavel Machek <pavel@....cz>, Dan Murphy <dmurphy@...com>,
Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
Jiri Slaby <jslaby@...e.com>
Cc: linux-leds@...r.kernel.org, linux-kernel@...r.kernel.org,
kernel@...gutronix.de, linux-serial@...r.kernel.org
Subject: [PATCH v6 1/4] lib: new helper kstrtodev_t()
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@...ine-koenig.org>
---
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
Powered by blists - more mailing lists