[PATCH v1 1/2] vsprintf: introduce %dE for error constants
From: Uwe Kleine-KÃnig
Date: Sat Aug 24 2019 - 19:37:45 EST
pr_info("probing failed (%dE)\n", ret);
expands to
probing failed (EIO)
if ret holds -EIO (or EIO). This introduces an array of error codes. If
the error code is missing, %dE falls back to %d and so prints the plain
number.
Signed-off-by: Uwe Kleine-KÃnig <uwe@xxxxxxxxxxxxxxxxx>
---
Hello
there are many code sites that benefit from this. Just grep for
"(%d)" ...
As an example the follow up patch converts a printk to use this new
format escape.
Best regards
Uwe
Documentation/core-api/printk-formats.rst | 3 +
lib/vsprintf.c | 193 +++++++++++++++++++++-
2 files changed, 195 insertions(+), 1 deletion(-)
diff --git a/Documentation/core-api/printk-formats.rst b/Documentation/core-api/printk-formats.rst
index c6224d039bcb..81002414f956 100644
--- a/Documentation/core-api/printk-formats.rst
+++ b/Documentation/core-api/printk-formats.rst
@@ -35,6 +35,9 @@ Integer types
u64 %llu or %llx
+To print the name that corresponds to an integer error constant, use %dE and
+pass the int.
+
If <type> is dependent on a config option for its size (e.g., sector_t,
blkcnt_t) or is architecture-dependent for its size (e.g., tcflag_t), use a
format specifier of its largest possible type and explicitly cast to it.
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index b0967cf17137..672eab8dab84 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -533,6 +533,192 @@ char *number(char *buf, char *end, unsigned long long num,
return buf;
}
+#define ERRORCODE(x) { .str = #x, .err = x }
+
+static const struct {
+ const char *str;
+ int err;
+} errorcodes[] = {
+ ERRORCODE(EPERM),
+ ERRORCODE(ENOENT),
+ ERRORCODE(ESRCH),
+ ERRORCODE(EINTR),
+ ERRORCODE(EIO),
+ ERRORCODE(ENXIO),
+ ERRORCODE(E2BIG),
+ ERRORCODE(ENOEXEC),
+ ERRORCODE(EBADF),
+ ERRORCODE(ECHILD),
+ ERRORCODE(EAGAIN),
+ ERRORCODE(ENOMEM),
+ ERRORCODE(EACCES),
+ ERRORCODE(EFAULT),
+ ERRORCODE(ENOTBLK),
+ ERRORCODE(EBUSY),
+ ERRORCODE(EEXIST),
+ ERRORCODE(EXDEV),
+ ERRORCODE(ENODEV),
+ ERRORCODE(ENOTDIR),
+ ERRORCODE(EISDIR),
+ ERRORCODE(EINVAL),
+ ERRORCODE(ENFILE),
+ ERRORCODE(EMFILE),
+ ERRORCODE(ENOTTY),
+ ERRORCODE(ETXTBSY),
+ ERRORCODE(EFBIG),
+ ERRORCODE(ENOSPC),
+ ERRORCODE(ESPIPE),
+ ERRORCODE(EROFS),
+ ERRORCODE(EMLINK),
+ ERRORCODE(EPIPE),
+ ERRORCODE(EDOM),
+ ERRORCODE(ERANGE),
+ ERRORCODE(EDEADLK),
+ ERRORCODE(ENAMETOOLONG),
+ ERRORCODE(ENOLCK),
+ ERRORCODE(ENOSYS),
+ ERRORCODE(ENOTEMPTY),
+ ERRORCODE(ELOOP),
+ ERRORCODE(EWOULDBLOCK),
+ ERRORCODE(ENOMSG),
+ ERRORCODE(EIDRM),
+ ERRORCODE(ECHRNG),
+ ERRORCODE(EL2NSYNC),
+ ERRORCODE(EL3HLT),
+ ERRORCODE(EL3RST),
+ ERRORCODE(ELNRNG),
+ ERRORCODE(EUNATCH),
+ ERRORCODE(ENOCSI),
+ ERRORCODE(EL2HLT),
+ ERRORCODE(EBADE),
+ ERRORCODE(EBADR),
+ ERRORCODE(EXFULL),
+ ERRORCODE(ENOANO),
+ ERRORCODE(EBADRQC),
+ ERRORCODE(EBADSLT),
+ ERRORCODE(EBFONT),
+ ERRORCODE(ENOSTR),
+ ERRORCODE(ENODATA),
+ ERRORCODE(ETIME),
+ ERRORCODE(ENOSR),
+ ERRORCODE(ENONET),
+ ERRORCODE(ENOPKG),
+ ERRORCODE(EREMOTE),
+ ERRORCODE(ENOLINK),
+ ERRORCODE(EADV),
+ ERRORCODE(ESRMNT),
+ ERRORCODE(ECOMM),
+ ERRORCODE(EPROTO),
+ ERRORCODE(EMULTIHOP),
+ ERRORCODE(EDOTDOT),
+ ERRORCODE(EBADMSG),
+ ERRORCODE(EOVERFLOW),
+ ERRORCODE(ENOTUNIQ),
+ ERRORCODE(EBADFD),
+ ERRORCODE(EREMCHG),
+ ERRORCODE(ELIBACC),
+ ERRORCODE(ELIBBAD),
+ ERRORCODE(ELIBSCN),
+ ERRORCODE(ELIBMAX),
+ ERRORCODE(ELIBEXEC),
+ ERRORCODE(EILSEQ),
+ ERRORCODE(ERESTART),
+ ERRORCODE(ESTRPIPE),
+ ERRORCODE(EUSERS),
+ ERRORCODE(ENOTSOCK),
+ ERRORCODE(EDESTADDRREQ),
+ ERRORCODE(EMSGSIZE),
+ ERRORCODE(EPROTOTYPE),
+ ERRORCODE(ENOPROTOOPT),
+ ERRORCODE(EPROTONOSUPPORT),
+ ERRORCODE(ESOCKTNOSUPPORT),
+ ERRORCODE(EOPNOTSUPP),
+ ERRORCODE(EPFNOSUPPORT),
+ ERRORCODE(EAFNOSUPPORT),
+ ERRORCODE(EADDRINUSE),
+ ERRORCODE(EADDRNOTAVAIL),
+ ERRORCODE(ENETDOWN),
+ ERRORCODE(ENETUNREACH),
+ ERRORCODE(ENETRESET),
+ ERRORCODE(ECONNABORTED),
+ ERRORCODE(ECONNRESET),
+ ERRORCODE(ENOBUFS),
+ ERRORCODE(EISCONN),
+ ERRORCODE(ENOTCONN),
+ ERRORCODE(ESHUTDOWN),
+ ERRORCODE(ETOOMANYREFS),
+ ERRORCODE(ETIMEDOUT),
+ ERRORCODE(ECONNREFUSED),
+ ERRORCODE(EHOSTDOWN),
+ ERRORCODE(EHOSTUNREACH),
+ ERRORCODE(EALREADY),
+ ERRORCODE(EINPROGRESS),
+ ERRORCODE(ESTALE),
+ ERRORCODE(EUCLEAN),
+ ERRORCODE(ENOTNAM),
+ ERRORCODE(ENAVAIL),
+ ERRORCODE(EISNAM),
+ ERRORCODE(EREMOTEIO),
+ ERRORCODE(EDQUOT),
+ ERRORCODE(ENOMEDIUM),
+ ERRORCODE(EMEDIUMTYPE),
+ ERRORCODE(ECANCELED),
+ ERRORCODE(ENOKEY),
+ ERRORCODE(EKEYEXPIRED),
+ ERRORCODE(EKEYREVOKED),
+ ERRORCODE(EKEYREJECTED),
+ ERRORCODE(EOWNERDEAD),
+ ERRORCODE(ENOTRECOVERABLE),
+ ERRORCODE(ERFKILL),
+ ERRORCODE(EHWPOISON),
+ ERRORCODE(ERESTARTSYS),
+ ERRORCODE(ERESTARTNOINTR),
+ ERRORCODE(ERESTARTNOHAND),
+ ERRORCODE(ENOIOCTLCMD),
+ ERRORCODE(ERESTART_RESTARTBLOCK),
+ ERRORCODE(EPROBE_DEFER),
+ ERRORCODE(EOPENSTALE),
+ ERRORCODE(ENOPARAM),
+ ERRORCODE(EBADHANDLE),
+ ERRORCODE(ENOTSYNC),
+ ERRORCODE(EBADCOOKIE),
+ ERRORCODE(ENOTSUPP),
+ ERRORCODE(ETOOSMALL),
+ ERRORCODE(ESERVERFAULT),
+ ERRORCODE(EBADTYPE),
+ ERRORCODE(EJUKEBOX),
+ ERRORCODE(EIOCBQUEUED),
+ ERRORCODE(ERECALLCONFLICT),
+};
+
+static noinline_for_stack
+char *errstr(char *buf, char *end, unsigned long long num,
+ struct printf_spec spec)
+{
+ char *errname = NULL;
+ size_t errnamelen, copy;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(errorcodes); ++i) {
+ if (num == errorcodes[i].err || num == -errorcodes[i].err) {
+ errname = errorcodes[i].str;
+ break;
+ }
+ }
+
+ if (!errname) {
+ /* fall back to ordinary number */
+ return number(buf, end, num, spec);
+ }
+
+ copy = errnamelen = strlen(errname);
+ if (copy > end - buf)
+ copy = end - buf;
+ buf = memcpy(buf, errname, copy);
+
+ return buf + errnamelen;
+}
+
static noinline_for_stack
char *special_hex_number(char *buf, char *end, unsigned long long num, int size)
{
@@ -2566,7 +2752,12 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
num = va_arg(args, unsigned int);
}
- str = number(str, end, num, spec);
+ if (spec.type == FORMAT_TYPE_INT && *fmt == 'E') {
+ fmt++;
+ str = errstr(str, end, num, spec);
+ } else {
+ str = number(str, end, num, spec);
+ }
}
}
--
2.20.1