[RFC v8 16/20] um: host: add utilities functions
Hajime Tazaki
thehajime at gmail.com
Tue Jan 19 21:27:21 EST 2021
Add basic utility functions for getting a string from a kernel error
code and a fprintf like function that uses the host print
operation. The latter is useful for informing the user about errors
that occur in the host library.
Signed-off-by: Hajime Tazaki <thehajime at gmail.com>
---
tools/um/include/lkl.h | 23 +++++
tools/um/lib/Build | 3 +
tools/um/lib/utils.c | 205 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 231 insertions(+)
create mode 100644 tools/um/lib/Build
create mode 100644 tools/um/lib/utils.c
diff --git a/tools/um/include/lkl.h b/tools/um/include/lkl.h
index 2417ed5ccf71..97da2d11502f 100644
--- a/tools/um/include/lkl.h
+++ b/tools/um/include/lkl.h
@@ -27,6 +27,29 @@ extern "C" {
#undef class
#endif
+/**
+ * lkl_printf - print a message via the host print operation
+ *
+ * @fmt: printf like format string
+ */
+int lkl_printf(const char *fmt, ...);
+
+/**
+ * lkl_strerror - returns a string describing the given error code
+ *
+ * @err - error code
+ * @returns - string for the given error code
+ */
+const char *lkl_strerror(int err);
+
+/**
+ * lkl_perror - prints a string describing the given error code
+ *
+ * @msg - prefix for the error message
+ * @err - error code
+ */
+void lkl_perror(char *msg, int err);
+
#if __LKL__BITS_PER_LONG == 64
#define lkl_sys_fstatat lkl_sys_newfstatat
#define lkl_sys_fstat lkl_sys_newfstat
diff --git a/tools/um/lib/Build b/tools/um/lib/Build
new file mode 100644
index 000000000000..77acd6f55e76
--- /dev/null
+++ b/tools/um/lib/Build
@@ -0,0 +1,3 @@
+include $(objtree)/include/config/auto.conf
+
+liblinux-$(CONFIG_UMMODE_LIB) += utils.o
diff --git a/tools/um/lib/utils.c b/tools/um/lib/utils.c
new file mode 100644
index 000000000000..3b38e1a95124
--- /dev/null
+++ b/tools/um/lib/utils.c
@@ -0,0 +1,205 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <lkl_host.h>
+
+static const char * const lkl_err_strings[] = {
+ [0] = "Success",
+ [LKL_EPERM] = "Operation not permitted",
+ [LKL_ENOENT] = "No such file or directory",
+ [LKL_ESRCH] = "No such process",
+ [LKL_EINTR] = "Interrupted system call",
+ [LKL_EIO] = "I/O error",
+ [LKL_ENXIO] = "No such device or address",
+ [LKL_E2BIG] = "Argument list too long",
+ [LKL_ENOEXEC] = "Exec format error",
+ [LKL_EBADF] = "Bad file number",
+ [LKL_ECHILD] = "No child processes",
+ [LKL_EAGAIN] = "Try again",
+ [LKL_ENOMEM] = "Out of memory",
+ [LKL_EACCES] = "Permission denied",
+ [LKL_EFAULT] = "Bad address",
+ [LKL_ENOTBLK] = "Block device required",
+ [LKL_EBUSY] = "Device or resource busy",
+ [LKL_EEXIST] = "File exists",
+ [LKL_EXDEV] = "Cross-device link",
+ [LKL_ENODEV] = "No such device",
+ [LKL_ENOTDIR] = "Not a directory",
+ [LKL_EISDIR] = "Is a directory",
+ [LKL_EINVAL] = "Invalid argument",
+ [LKL_ENFILE] = "File table overflow",
+ [LKL_EMFILE] = "Too many open files",
+ [LKL_ENOTTY] = "Not a typewriter",
+ [LKL_ETXTBSY] = "Text file busy",
+ [LKL_EFBIG] = "File too large",
+ [LKL_ENOSPC] = "No space left on device",
+ [LKL_ESPIPE] = "Illegal seek",
+ [LKL_EROFS] = "Read-only file system",
+ [LKL_EMLINK] = "Too many links",
+ [LKL_EPIPE] = "Broken pipe",
+ [LKL_EDOM] = "Math argument out of domain of func",
+ [LKL_ERANGE] = "Math result not representable",
+ [LKL_EDEADLK] = "Resource deadlock would occur",
+ [LKL_ENAMETOOLONG] = "File name too long",
+ [LKL_ENOLCK] = "No record locks available",
+ [LKL_ENOSYS] = "Invalid system call number",
+ [LKL_ENOTEMPTY] = "Directory not empty",
+ [LKL_ELOOP] = "Too many symbolic links encountered",
+ [LKL_ENOMSG] = "No message of desired type",
+ [LKL_EIDRM] = "Identifier removed",
+ [LKL_ECHRNG] = "Channel number out of range",
+ [LKL_EL2NSYNC] = "Level 2 not synchronized",
+ [LKL_EL3HLT] = "Level 3 halted",
+ [LKL_EL3RST] = "Level 3 reset",
+ [LKL_ELNRNG] = "Link number out of range",
+ [LKL_EUNATCH] = "Protocol driver not attached",
+ [LKL_ENOCSI] = "No CSI structure available",
+ [LKL_EL2HLT] = "Level 2 halted",
+ [LKL_EBADE] = "Invalid exchange",
+ [LKL_EBADR] = "Invalid request descriptor",
+ [LKL_EXFULL] = "Exchange full",
+ [LKL_ENOANO] = "No anode",
+ [LKL_EBADRQC] = "Invalid request code",
+ [LKL_EBADSLT] = "Invalid slot",
+ [LKL_EBFONT] = "Bad font file format",
+ [LKL_ENOSTR] = "Device not a stream",
+ [LKL_ENODATA] = "No data available",
+ [LKL_ETIME] = "Timer expired",
+ [LKL_ENOSR] = "Out of streams resources",
+ [LKL_ENONET] = "Machine is not on the network",
+ [LKL_ENOPKG] = "Package not installed",
+ [LKL_EREMOTE] = "Object is remote",
+ [LKL_ENOLINK] = "Link has been severed",
+ [LKL_EADV] = "Advertise error",
+ [LKL_ESRMNT] = "Srmount error",
+ [LKL_ECOMM] = "Communication error on send",
+ [LKL_EPROTO] = "Protocol error",
+ [LKL_EMULTIHOP] = "Multihop attempted",
+ [LKL_EDOTDOT] = "RFS specific error",
+ [LKL_EBADMSG] = "Not a data message",
+ [LKL_EOVERFLOW] = "Value too large for defined data type",
+ [LKL_ENOTUNIQ] = "Name not unique on network",
+ [LKL_EBADFD] = "File descriptor in bad state",
+ [LKL_EREMCHG] = "Remote address changed",
+ [LKL_ELIBACC] = "Can not access a needed shared library",
+ [LKL_ELIBBAD] = "Accessing a corrupted shared library",
+ [LKL_ELIBSCN] = ".lib section in a.out corrupted",
+ [LKL_ELIBMAX] = "Attempting to link in too many shared libraries",
+ [LKL_ELIBEXEC] = "Cannot exec a shared library directly",
+ [LKL_EILSEQ] = "Illegal byte sequence",
+ [LKL_ERESTART] = "Interrupted system call should be restarted",
+ [LKL_ESTRPIPE] = "Streams pipe error",
+ [LKL_EUSERS] = "Too many users",
+ [LKL_ENOTSOCK] = "Socket operation on non-socket",
+ [LKL_EDESTADDRREQ] = "Destination address required",
+ [LKL_EMSGSIZE] = "Message too long",
+ [LKL_EPROTOTYPE] = "Protocol wrong type for socket",
+ [LKL_ENOPROTOOPT] = "Protocol not available",
+ [LKL_EPROTONOSUPPORT] = "Protocol not supported",
+ [LKL_ESOCKTNOSUPPORT] = "Socket type not supported",
+ [LKL_EOPNOTSUPP] = "Operation not supported on transport endpoint",
+ [LKL_EPFNOSUPPORT] = "Protocol family not supported",
+ [LKL_EAFNOSUPPORT] = "Address family not supported by protocol",
+ [LKL_EADDRINUSE] = "Address already in use",
+ [LKL_EADDRNOTAVAIL] = "Cannot assign requested address",
+ [LKL_ENETDOWN] = "Network is down",
+ [LKL_ENETUNREACH] = "Network is unreachable",
+ [LKL_ENETRESET] = "Network dropped connection because of reset",
+ [LKL_ECONNABORTED] = "Software caused connection abort",
+ [LKL_ECONNRESET] = "Connection reset by peer",
+ [LKL_ENOBUFS] = "No buffer space available",
+ [LKL_EISCONN] = "Transport endpoint is already connected",
+ [LKL_ENOTCONN] = "Transport endpoint is not connected",
+ [LKL_ESHUTDOWN] = "Cannot send after transport endpoint shutdown",
+ [LKL_ETOOMANYREFS] = "Too many references: cannot splice",
+ [LKL_ETIMEDOUT] = "Connection timed out",
+ [LKL_ECONNREFUSED] = "Connection refused",
+ [LKL_EHOSTDOWN] = "Host is down",
+ [LKL_EHOSTUNREACH] = "No route to host",
+ [LKL_EALREADY] = "Operation already in progress",
+ [LKL_EINPROGRESS] = "Operation now in progress",
+ [LKL_ESTALE] = "Stale file handle",
+ [LKL_EUCLEAN] = "Structure needs cleaning",
+ [LKL_ENOTNAM] = "Not a XENIX named type file",
+ [LKL_ENAVAIL] = "No XENIX semaphores available",
+ [LKL_EISNAM] = "Is a named type file",
+ [LKL_EREMOTEIO] = "Remote I/O error",
+ [LKL_EDQUOT] = "Quota exceeded",
+ [LKL_ENOMEDIUM] = "No medium found",
+ [LKL_EMEDIUMTYPE] = "Wrong medium type",
+ [LKL_ECANCELED] = "Operation Canceled",
+ [LKL_ENOKEY] = "Required key not available",
+ [LKL_EKEYEXPIRED] = "Key has expired",
+ [LKL_EKEYREVOKED] = "Key has been revoked",
+ [LKL_EKEYREJECTED] = "Key was rejected by service",
+ [LKL_EOWNERDEAD] = "Owner died",
+ [LKL_ENOTRECOVERABLE] = "State not recoverable",
+ [LKL_ERFKILL] = "Operation not possible due to RF-kill",
+ [LKL_EHWPOISON] = "Memory page has hardware error",
+};
+
+const char *lkl_strerror(int err)
+{
+ if (err < 0)
+ err = -err;
+
+ if ((size_t)err >= sizeof(lkl_err_strings) / sizeof(const char *))
+ return "Bad error code";
+
+ return lkl_err_strings[err];
+}
+
+void lkl_perror(char *msg, int err)
+{
+ const char *err_msg = lkl_strerror(err);
+ /* We need to use 'real' printf because lkl_print can
+ * be turned off when debugging is off.
+ */
+ lkl_printf("%s: %s\n", msg, err_msg);
+}
+
+static int lkl_vprintf(const char *fmt, va_list args)
+{
+ int n;
+ char *buffer;
+ va_list copy;
+
+ va_copy(copy, args);
+ n = vsnprintf(NULL, 0, fmt, copy);
+ va_end(copy);
+
+ buffer = lkl_mem_alloc(n + 1);
+ if (!buffer)
+ return (-1);
+
+ vsnprintf(buffer, n + 1, fmt, args);
+
+ lkl_print(buffer, n);
+ lkl_mem_free(buffer);
+
+ return n;
+}
+
+int lkl_printf(const char *fmt, ...)
+{
+ int n;
+ va_list args;
+
+ va_start(args, fmt);
+ n = lkl_vprintf(fmt, args);
+ va_end(args);
+
+ return n;
+}
+
+void lkl_bug(const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ lkl_vprintf(fmt, args);
+ va_end(args);
+
+ lkl_panic();
+}
--
2.21.0 (Apple Git-122.2)
More information about the linux-um
mailing list