1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

Merge pull request #18571 from maribu/sys/tiny_strerror

sys/tiny_strerror: add tiny `strerror()` implementation
This commit is contained in:
Marian Buschsieweke 2022-10-05 09:24:40 +02:00 committed by GitHub
commit f02bc5791a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 297 additions and 196 deletions

View File

@ -12,6 +12,7 @@ config CPU_ARCH_AVR8
select HAS_ARCH_AVR8
select MODULE_MALLOC_THREAD_SAFE if TEST_KCONFIG
select MODULE_TINY_STRERROR_AS_STRERROR if TEST_KCONFIG
# static C++ constructors need guards for thread safe initialization
select MODULE_CXX_CTOR_GUARDS if MODULE_CPP
# new and delete operators needed

View File

@ -9,6 +9,9 @@ USEMODULE += avr8_common
# instead.
USEMODULE += malloc_thread_safe
# The AVR-libc provides no strerror, so we provide it via tiny_strerror
USEMODULE += tiny_strerror_as_strerror
# the atmel port uses stdio_uart by default
ifeq (,$(filter stdio_% slipdev_stdio,$(USEMODULE)))
USEMODULE += stdio_uart

View File

@ -177,80 +177,4 @@ ssize_t write(int fd, const void *src, size_t count)
#endif
}
const char *strerror(int errnum)
{
if (errnum < 0) {
errnum = -errnum;
}
switch (errnum) {
case 0: return "OK";
case EDOM: return "EDOM";
case ERANGE: return "ERANGE";
case ENOSYS: return "ENOSYS";
case EINTR: return "EINTR";
case E2BIG: return "E2BIG";
case EACCES: return "EACCES";
case EADDRINUSE: return "EADDRINUSE";
case EADDRNOTAVAIL: return "EADDRNOTAVAIL";
case EAFNOSUPPORT: return "EAFNOSUPPORT";
case EAGAIN: return "EAGAIN";
case EALREADY: return "EALREADY";
case EBADF: return "EBADF";
case EBUSY: return "EBUSY";
case ECHILD: return "ECHILD";
case ECONNABORTED: return "ECONNABORTED";
case ECONNREFUSED: return "ECONNREFUSED";
case ECONNRESET: return "ECONNRESET";
case EDEADLK: return "EDEADLK";
case EDESTADDRREQ: return "EDESTADDRREQ";
case EEXIST: return "EEXIST";
case EFAULT: return "EFAULT";
case EFBIG: return "EFBIG";
case EHOSTUNREACH: return "EHOSTUNREACH";
case EILSEQ: return "EILSEQ";
case EINPROGRESS: return "EINPROGRESS";
case EINVAL: return "EINVAL";
case EIO: return "EIO";
case EISCONN: return "EISCONN";
case EISDIR: return "EISDIR";
case ELOOP: return "ELOOP";
case EMFILE: return "EMFILE";
case EMLINK: return "EMLINK";
case EMSGSIZE: return "EMSGSIZE";
case ENAMETOOLONG: return "ENAMETOOLONG";
case ENETDOWN: return "ENETDOWN";
case ENETRESET: return "ENETRESET";
case ENETUNREACH: return "ENETUNREACH";
case ENFILE: return "ENFILE";
case ENOBUFS: return "ENOBUFS";
case ENODEV: return "ENODEV";
case ENOENT: return "ENOENT";
case ENOEXEC: return "ENOEXEC";
case ENOLCK: return "ENOLCK";
case ENOMEM: return "ENOMEM";
case ENOMSG: return "ENOMSG";
case ENOPROTOOPT: return "ENOPROTOOPT";
case ENOSPC: return "ENOSPC";
case ENOTCONN: return "ENOTCONN";
case ENOTDIR: return "ENOTDIR";
case ENOTEMPTY: return "ENOTEMPTY";
case ENOTSOCK: return "ENOTSOCK";
case ENOTTY: return "ENOTTY";
case ENXIO: return "ENXIO";
case EOPNOTSUPP: return "EOPNOTSUPP";
case EPERM: return "EPERM";
case EPIPE: return "EPIPE";
case EPROTONOSUPPORT: return "EPROTONOSUPPORT";
case EPROTOTYPE: return "EPROTOTYPE";
case EROFS: return "EROFS";
case ESPIPE: return "ESPIPE";
case ESRCH: return "ESRCH";
case ETIMEDOUT: return "ETIMEDOUT";
case EWOULDBLOCK: return "EWOULDBLOCK";
case EXDEV: return "EXDEV";
default: return "unknown";
}
}
/** @} */

View File

@ -290,6 +290,7 @@ PSEUDOMODULES += stm32mp1_eng_mode
PSEUDOMODULES += suit_transport_%
PSEUDOMODULES += suit_storage_%
PSEUDOMODULES += sys_bus_%
PSEUDOMODULES += tiny_strerror_as_strerror
PSEUDOMODULES += vdd_lc_filter_%
## @defgroup pseudomodule_vfs_auto_format vfs_auto_format
## @brief Format mount points at startup unless they can be mounted

View File

@ -64,6 +64,7 @@ rsource "Kconfig.picolibc"
endmenu # Libc
rsource "Kconfig.stdio"
rsource "log/Kconfig"
rsource "luid/Kconfig"
rsource "malloc_thread_safe/Kconfig"
@ -71,12 +72,11 @@ rsource "matstat/Kconfig"
rsource "memarray/Kconfig"
rsource "mineplex/Kconfig"
rsource "net/Kconfig"
rsource "Kconfig.stdio"
rsource "od/Kconfig"
rsource "posix/Kconfig"
rsource "oneway-malloc/Kconfig"
rsource "phydat/Kconfig"
rsource "pm_layered/Kconfig"
rsource "posix/Kconfig"
rsource "progress_bar/Kconfig"
rsource "ps/Kconfig"
rsource "random/Kconfig"
@ -90,6 +90,7 @@ rsource "seq/Kconfig"
rsource "shell/Kconfig"
rsource "test_utils/Kconfig"
rsource "timex/Kconfig"
rsource "tiny_strerror/Kconfig"
rsource "trace/Kconfig"
rsource "tsrb/Kconfig"
rsource "uri_parser/Kconfig"

View File

@ -209,6 +209,9 @@ endif
ifneq (,$(filter test_utils_result_output,$(USEMODULE)))
DIRS += test_utils/result_output
endif
ifneq (,$(filter tiny_strerror,$(USEMODULE)))
DIRS += tiny_strerror
endif
ifneq (,$(filter udp,$(USEMODULE)))
DIRS += net/transport_layer/udp
endif

View File

@ -901,6 +901,10 @@ ifneq (,$(filter suit_%,$(USEMODULE)))
USEMODULE += suit
endif
ifneq (,$(filter tiny_strerror_as_strerror,$(USEMODULE)))
USEMODULE += tiny_strerror
endif
# include ztimer dependencies
ifneq (,$(filter ztimer ztimer_% %ztimer,$(USEMODULE)))
include $(RIOTBASE)/sys/ztimer/Makefile.dep

View File

@ -173,3 +173,7 @@ PSEUDOMODULES += shell_democommands
ifneq (,$(filter rust_riotmodules,$(USEMODULE)))
include $(RIOTBASE)/sys/rust_riotmodules/Makefile.include
endif
ifneq (,$(filter tiny_strerror,$(USEMODULE)))
include $(RIOTBASE)/sys/tiny_strerror/Makefile.include
endif

View File

@ -0,0 +1,76 @@
/*
* Copyright (C) 2021 ML!PA Consulting GmbH
* 2022 Otto-von-Guericke-Universität Magdeburg
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @defgroup sys_tiny_strerror Tiny strerror() implementation
* @ingroup sys
* @brief Tiny strerror() implementation
*
* Usage
* =====
*
* Select module `tiny_strerror` in order to use it.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}
* #include "tiny_strerror.h"
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* @note Using module `tiny_strerror_as_strerror` will replace all calls
* to `strerror()` by calls to `tiny_strerror()`, which may safe
* a bit of ROM.
* @{
*
*
* @file
* @brief Tiny strerror() implementation
*
* @author Benjamin Valentin <benjamin.valentin@ml-pa.com>
* @author Marian Buschsieweke <marian.buschsieweke@ovgu.de>
*/
#ifndef TINY_STRERROR_H
#define TINY_STRERROR_H
#include <errno.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Get the name of an errno macro
*
* @param[in] errnum Error code to get the name of
*
* Example:
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}
* puts(tiny_strerror(ENOENT)); // prints "ENOENT"
* puts(tiny_strerror(-ENXIO)); // prints "-ENXIO"
* puts(tiny_strerror(0)); // prints "OK"
* puts(tiny_strerror(1337)); // prints "unknown"
* puts(tiny_strerror(-1337)); // prints "-unknown"
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* @return String holding the macro name of the error given by @p errnum
*
* @retval `"OK"` If @p errnum is `0`
* @retval `"unknown"` If @p errnum is not matching any POSIX errno
* constant
* @retval `"-unknown"` If @p errnum is negative not matching any negative
* POSIX errno constant
*/
const char *tiny_strerror(int errnum);
#ifdef __cplusplus
}
#endif
#endif /* TINY_STRERROR_H */
/** @} */

View File

@ -281,6 +281,7 @@ ifneq (,$(filter shell_cmd_suit,$(USEMODULE)))
endif
ifneq (,$(filter shell_cmd_vfs,$(USEMODULE)))
USEMODULE += vfs
USEMODULE += tiny_strerror
endif
ifneq (,$(filter shell_democommands,$(USEMODULE)))

View File

@ -296,3 +296,4 @@ config MODULE_SHELL_CMD_VFS
default y if MODULE_SHELL_CMDS_DEFAULT
depends on MODULE_SHELL_CMDS
depends on MODULE_VFS
select MODULE_TINY_STRERROR

View File

@ -29,8 +29,9 @@
#include <unistd.h>
#include <fcntl.h>
#include "shell.h"
#include "macros/units.h"
#include "shell.h"
#include "tiny_strerror.h"
#include "vfs.h"
#include "vfs_util.h"
@ -93,51 +94,6 @@ static void _vfs_usage(char **argv)
puts("df: Show file system space utilization stats");
}
/* Macro used by _errno_string to expand errno labels to string and print it */
#define _case_snprintf_errno_name(x) \
case x: \
res = snprintf(buf, buflen, #x); \
break
static int _errno_string(int err, char *buf, size_t buflen)
{
int len = 0;
int res;
if (err < 0) {
res = snprintf(buf, buflen, "-");
if (res < 0) {
return res;
}
if ((size_t)res <= buflen) {
buf += res;
buflen -= res;
}
len += res;
err = -err;
}
switch (err) {
_case_snprintf_errno_name(EBUSY);
_case_snprintf_errno_name(EACCES);
_case_snprintf_errno_name(ENOENT);
_case_snprintf_errno_name(EINVAL);
_case_snprintf_errno_name(EFAULT);
_case_snprintf_errno_name(EROFS);
_case_snprintf_errno_name(EIO);
_case_snprintf_errno_name(ENAMETOOLONG);
_case_snprintf_errno_name(EPERM);
default:
res = snprintf(buf, buflen, "%d", err);
break;
}
if (res < 0) {
return res;
}
len += res;
return len;
}
#undef _case_snprintf_errno_name
static void _print_size(uint64_t size)
{
unsigned long len;
@ -175,9 +131,7 @@ static void _print_df(vfs_DIR *dir)
int res = vfs_dstatvfs(dir, &buf);
printf("%-16s ", dir->mp->mount_point);
if (res < 0) {
char err[16];
_errno_string(res, err, sizeof(err));
printf("statvfs failed: %s\n", err);
printf("statvfs failed: %s\n", tiny_strerror(res));
return;
}
@ -200,9 +154,7 @@ static int _df_handler(int argc, char **argv)
_print_df(&dir);
vfs_closedir(&dir);
} else {
char err[16];
_errno_string(res, err, sizeof(err));
printf("Failed to open `%s`: %s\n", path, err);
printf("Failed to open `%s`: %s\n", path, tiny_strerror(res));
}
}
else {
@ -223,11 +175,9 @@ static int _mount_handler(int argc, char **argv)
return -1;
}
char buf[16];
int res = vfs_mount_by_path(argv[1]);
if (res < 0) {
_errno_string(res, buf, sizeof(buf));
puts(buf);
puts(tiny_strerror(res));
}
return res;
@ -241,11 +191,9 @@ static int _umount_handler(int argc, char **argv)
return -1;
}
char buf[16];
int res = vfs_unmount_by_path(argv[1]);
if (res < 0) {
_errno_string(res, buf, sizeof(buf));
puts(buf);
puts(tiny_strerror(res));
}
return res;
@ -259,12 +207,10 @@ static int _remount_handler(int argc, char **argv)
return -1;
}
char buf[16];
vfs_unmount_by_path(argv[1]);
int res = vfs_mount_by_path(argv[1]);
if (res < 0) {
_errno_string(res, buf, sizeof(buf));
puts(buf);
puts(tiny_strerror(res));
}
return res;
@ -278,11 +224,9 @@ static int _format_handler(int argc, char **argv)
return -1;
}
char buf[16];
int res = vfs_format_by_path(argv[1]);
if (res < 0) {
_errno_string(res, buf, sizeof(buf));
puts(buf);
puts(tiny_strerror(res));
}
return res;
@ -308,22 +252,19 @@ static int _read_handler(int argc, char **argv)
int res;
res = vfs_normalize_path(path, path, strlen(path) + 1);
if (res < 0) {
_errno_string(res, (char *)buf, sizeof(buf));
printf("Invalid path \"%s\": %s\n", path, buf);
printf("Invalid path \"%s\": %s\n", path, tiny_strerror(res));
return 5;
}
int fd = vfs_open(path, O_RDONLY, 0);
if (fd < 0) {
_errno_string(fd, (char *)buf, sizeof(buf));
printf("Error opening file \"%s\": %s\n", path, buf);
printf("Error opening file \"%s\": %s\n", path, tiny_strerror(fd));
return 3;
}
res = vfs_lseek(fd, offset, SEEK_SET);
if (res < 0) {
_errno_string(res, (char *)buf, sizeof(buf));
printf("Seek error: %s\n", buf);
printf("Seek error: %s\n", tiny_strerror(res));
vfs_close(fd);
return 4;
}
@ -333,8 +274,7 @@ static int _read_handler(int argc, char **argv)
size_t line_len = (nbytes < sizeof(buf) ? nbytes : sizeof(buf));
res = vfs_read(fd, buf, line_len);
if (res < 0) {
_errno_string(res, (char *)buf, sizeof(buf));
printf("Read error: %s\n", buf);
printf("Read error: %s\n", tiny_strerror(res));
vfs_close(fd);
return 5;
}
@ -400,7 +340,6 @@ static inline int _dehex(char c)
static int _write_handler(int argc, char **argv)
{
char *w_buf;
char buf[16];
size_t nbytes = 0;
size_t nb_str = 0;
char *path = argv[1];
@ -475,15 +414,13 @@ static int _write_handler(int argc, char **argv)
int res;
res = vfs_normalize_path(path, path, strlen(path) + 1);
if (res < 0) {
_errno_string(res, (char *)buf, sizeof(buf));
printf("Invalid path \"%s\": %s\n", path, buf);
printf("Invalid path \"%s\": %s\n", path, tiny_strerror(res));
return 5;
}
int fd = vfs_open(path, flag, 0);
if (fd < 0) {
_errno_string(fd, (char *)buf, sizeof(buf));
printf("Error opening file \"%s\": %s\n", path, buf);
printf("Error opening file \"%s\": %s\n", path, tiny_strerror(fd));
return 3;
}
@ -491,8 +428,7 @@ static int _write_handler(int argc, char **argv)
while (nb_str > 0) {
res = vfs_write(fd, w_buf, nbytes);
if (res < 0) {
_errno_string(res, (char *)buf, sizeof(buf));
printf("Write error: %s\n", buf);
printf("Write error: %s\n", tiny_strerror(res));
vfs_close(fd);
return 4;
}
@ -511,8 +447,7 @@ static int _write_handler(int argc, char **argv)
uint8_t byte = _dehex(*w_buf) << 4 | _dehex(*(w_buf + 1));
res = vfs_write(fd, &byte, 1);
if (res < 0) {
_errno_string(res, (char *)buf, sizeof(buf));
printf("Write error: %s\n", buf);
printf("Write error: %s\n", tiny_strerror(res));
vfs_close(fd);
return 4;
}
@ -529,7 +464,6 @@ static int _write_handler(int argc, char **argv)
static int _cp_handler(int argc, char **argv)
{
char errbuf[16];
if (argc < 3) {
_vfs_usage(argv);
return 1;
@ -540,14 +474,14 @@ static int _cp_handler(int argc, char **argv)
int fd_in = vfs_open(src_name, O_RDONLY, 0);
if (fd_in < 0) {
_errno_string(fd_in, (char *)errbuf, sizeof(errbuf));
printf("Error opening file for reading \"%s\": %s\n", src_name, errbuf);
printf("Error opening file for reading \"%s\": %s\n", src_name,
tiny_strerror(fd_in));
return 2;
}
int fd_out = vfs_open(dest_name, O_WRONLY | O_TRUNC | O_CREAT, S_IRWXU | S_IRWXG | S_IRWXO);
if (fd_out < 0) {
_errno_string(fd_out, (char *)errbuf, sizeof(errbuf));
printf("Error opening file for writing \"%s\": %s\n", dest_name, errbuf);
printf("Error opening file for writing \"%s\": %s\n", dest_name,
tiny_strerror(fd_out));
return 2;
}
int eof = 0;
@ -557,9 +491,9 @@ static int _cp_handler(int argc, char **argv)
while (bufspace > 0) {
int res = vfs_read(fd_in, &_shell_vfs_data_buffer[pos], bufspace);
if (res < 0) {
_errno_string(res, (char *)errbuf, sizeof(errbuf));
printf("Error reading %lu bytes @ 0x%lx in \"%s\" (%d): %s\n",
(unsigned long)bufspace, (unsigned long)pos, src_name, fd_in, errbuf);
(unsigned long)bufspace, (unsigned long)pos, src_name,
fd_in, tiny_strerror(res));
vfs_close(fd_in);
vfs_close(fd_out);
return 2;
@ -583,9 +517,9 @@ static int _cp_handler(int argc, char **argv)
while (bufspace > 0) {
int res = vfs_write(fd_out, &_shell_vfs_data_buffer[pos], bufspace);
if (res <= 0) {
_errno_string(res, (char *)errbuf, sizeof(errbuf));
printf("Error writing %lu bytes @ 0x%lx in \"%s\" (%d): %s\n",
(unsigned long)bufspace, (unsigned long)pos, dest_name, fd_out, errbuf);
(unsigned long)bufspace, (unsigned long)pos, dest_name,
fd_out, tiny_strerror(res));
vfs_close(fd_in);
vfs_close(fd_out);
return 4;
@ -617,9 +551,7 @@ static int _mv_handler(int argc, char **argv)
int res = vfs_rename(src_name, dest_name);
if (res < 0) {
char errbuf[16];
_errno_string(res, (char *)errbuf, sizeof(errbuf));
printf("mv ERR: %s\n", errbuf);
printf("mv ERR: %s\n", tiny_strerror(res));
return 2;
}
return 0;
@ -647,9 +579,7 @@ static int _rm_handler(int argc, char **argv)
res = vfs_unlink(rm_name);
}
if (res < 0) {
char errbuf[16];
_errno_string(res, (char *)errbuf, sizeof(errbuf));
printf("rm ERR: %s\n", errbuf);
printf("rm ERR: %s\n", tiny_strerror(res));
return 2;
}
return 0;
@ -666,9 +596,7 @@ static int _mkdir_handler(int argc, char **argv)
int res = vfs_mkdir(dir_name, 0);
if (res < 0) {
char errbuf[16];
_errno_string(res, (char *)errbuf, sizeof(errbuf));
printf("mkdir ERR: %s\n", errbuf);
printf("mkdir ERR: %s\n", tiny_strerror(res));
return 2;
}
return 0;
@ -681,20 +609,17 @@ static int _ls_handler(int argc, char **argv)
return 1;
}
char *path = argv[1];
uint8_t buf[16];
int res;
int ret = 0;
res = vfs_normalize_path(path, path, strlen(path) + 1);
if (res < 0) {
_errno_string(res, (char *)buf, sizeof(buf));
printf("Invalid path \"%s\": %s\n", path, buf);
printf("Invalid path \"%s\": %s\n", path, tiny_strerror(res));
return 5;
}
vfs_DIR dir;
res = vfs_opendir(&dir, path);
if (res < 0) {
_errno_string(res, (char *)buf, sizeof(buf));
printf("vfs_opendir error: %s\n", buf);
printf("vfs_opendir error: %s\n", tiny_strerror(res));
return 1;
}
unsigned int nfiles = 0;
@ -706,8 +631,7 @@ static int _ls_handler(int argc, char **argv)
res = vfs_readdir(&dir, &entry);
if (res < 0) {
_errno_string(res, (char *)buf, sizeof(buf));
printf("vfs_readdir error: %s\n", buf);
printf("vfs_readdir error: %s\n", tiny_strerror(res));
if (res == -EAGAIN) {
/* try again */
continue;
@ -737,8 +661,7 @@ static int _ls_handler(int argc, char **argv)
res = vfs_closedir(&dir);
if (res < 0) {
_errno_string(res, (char *)buf, sizeof(buf));
printf("vfs_closedir error: %s\n", buf);
printf("vfs_closedir error: %s\n", tiny_strerror(res));
return 2;
}
return ret;
@ -797,6 +720,7 @@ static int _vfs_handler(int argc, char **argv)
SHELL_COMMAND(vfs, "virtual file system operations", _vfs_handler);
__attribute__((used)) /* only used if md5sum / sha1sum / sha256sum is used */
static inline void _print_digest(const uint8_t *digest, size_t len, const char *file)
{
for (unsigned i = 0; i < len; ++i) {
@ -867,7 +791,6 @@ SHELL_COMMAND(sha1sum, "Compute and check SHA1 message digest", _vfs_sha1sum_cmd
#include "hashes/sha256.h"
static int _vfs_sha256sum_cmd(int argc, char **argv)
{
int res;
uint8_t digest[SHA256_DIGEST_LENGTH];
if (argc < 2) {
@ -877,10 +800,10 @@ static int _vfs_sha256sum_cmd(int argc, char **argv)
for (int i = 1; i < argc; ++i) {
const char *file = argv[i];
res = vfs_file_sha256(file, digest,
_shell_vfs_data_buffer, sizeof(_shell_vfs_data_buffer));
int res = vfs_file_sha256(file, digest, _shell_vfs_data_buffer,
sizeof(_shell_vfs_data_buffer));
if (res < 0) {
printf("%s: error %d\n", file, res);
printf("%s: error %s\n", file, tiny_strerror(res));
} else {
_print_digest(digest, sizeof(digest), file);
}

22
sys/tiny_strerror/Kconfig Normal file
View File

@ -0,0 +1,22 @@
# Copyright (C) 2022 Otto-von-Guericke-Universität Magdeburg
#
# This file is subject to the terms and conditions of the GNU Lesser
# General Public License v2.1. See the file LICENSE in the top level
# directory for more details.
#
config MODULE_TINY_STRERROR
bool
depends on TEST_KCONFIG
help
This module provides `tiny_strerror()`, a drop-in replacement for
`strerror()` that returns the errno macro name rather than a verbose
help description string.
config MODULE_TINY_STRERROR_AS_STRERROR
bool
depends on TEST_KCONFIG
select MODULE_TINY_STRERROR
help
This replaces all calls to `strerror()` with calls to `tiny_strerror()`
via linker magic. This may safe a bit of ROM.

View File

@ -0,0 +1 @@
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,4 @@
ifneq (,$(filter tiny_strerror_as_strerror,$(USEMODULE)))
# use the wrapper functions for strerror
LINKFLAGS += -Wl,-wrap=strerror
endif

View File

@ -0,0 +1,132 @@
/*
* Copyright (C) 2021 ML!PA Consulting GmbH
* 2022 Otto-von-Guericke-Universität Magdeburg
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @{
*
* @file
* @brief Tiny strerror() implementation
*
* @author Benjamin Valentin <benjamin.valentin@ml-pa.com>
* @author Marian Buschsieweke <marian.buschsieweke@ovgu.de>
*/
#include <errno.h>
#include <string.h>
#include "kernel_defines.h"
#include "tiny_strerror.h"
static const char *lookup[] = {
[0] = "OK",
[E2BIG] = "-E2BIG",
[EACCES] = "-EACCES",
[EADDRINUSE] = "-EADDRINUSE",
[EADDRNOTAVAIL] = "-EADDRNOTAVAIL",
[EAFNOSUPPORT] = "-EAFNOSUPPORT",
[EAGAIN] = "-EAGAIN",
[EALREADY] = "-EALREADY",
[EBADF] = "-EBADF",
[EBADMSG] = "-EBADMSG",
[EBUSY] = "-EBUSY",
[ECANCELED] = "-ECANCELED",
[ECHILD] = "-ECHILD",
[ECONNABORTED] = "-ECONNABORTED",
[ECONNREFUSED] = "-ECONNREFUSED",
[ECONNRESET] = "-ECONNRESET",
[EDEADLK] = "-EDEADLK",
[EDESTADDRREQ] = "-EDESTADDRREQ",
[EDOM] = "-EDOM",
[EEXIST] = "-EEXIST",
[EFAULT] = "-EFAULT",
[EFBIG] = "-EFBIG",
[EHOSTUNREACH] = "-EHOSTUNREACH",
[EILSEQ] = "-EILSEQ",
[EINPROGRESS] = "-EINPROGRESS",
[EINTR] = "-EINTR",
[EINVAL] = "-EINVAL",
[EIO] = "-EIO",
[EISCONN] = "-EISCONN",
[EISDIR] = "-EISDIR",
[ELOOP] = "-ELOOP",
[EMFILE] = "-EMFILE",
[EMLINK] = "-EMLINK",
[EMSGSIZE] = "-EMSGSIZE",
[ENAMETOOLONG] = "-ENAMETOOLONG",
[ENETDOWN] = "-ENETDOWN",
[ENETRESET] = "-ENETRESET",
[ENETUNREACH] = "-ENETUNREACH",
[ENFILE] = "-ENFILE",
[ENOBUFS] = "-ENOBUFS",
[ENODEV] = "-ENODEV",
[ENOENT] = "-ENOENT",
[ENOEXEC] = "-ENOEXEC",
[ENOLCK] = "-ENOLCK",
[ENOMEM] = "-ENOMEM",
[ENOMSG] = "-ENOMSG",
[ENOPROTOOPT] = "-ENOPROTOOPT",
[ENOSPC] = "-ENOSPC",
[ENOSYS] = "-ENOSYS",
[ENOTCONN] = "-ENOTCONN",
[ENOTDIR] = "-ENOTDIR",
[ENOTEMPTY] = "-ENOTEMPTY",
[ENOTSOCK] = "-ENOTSOCK",
[ENOTSUP] = "-ENOTSUP",
[ENOTTY] = "-ENOTTY",
[ENXIO] = "-ENXIO",
[EPERM] = "-EPERM",
[EPIPE] = "-EPIPE",
[EPROTONOSUPPORT] = "-EPROTONOSUPPORT",
[EPROTOTYPE] = "-EPROTOTYPE",
[ERANGE] = "-ERANGE",
[EROFS] = "-EROFS",
[ESPIPE] = "-ESPIPE",
[ESRCH] = "-ESRCH",
[ETIMEDOUT] = "-ETIMEDOUT",
[EXDEV] = "-EXDEV",
/* EAGAIN and EWOULDBLOCK have the exact same meaning and consequently may
* have the same numeric value */
#if EAGAIN != EWOULDBLOCK
[EWOULDBLOCK] = "-EWOULDBLOCK",
#endif
/* ENOTSUP and EOPNOTSUPP do not have the exact same meaning. Still, they
* have the same numeric value on Linux, breaking POSIX standard */
#if ENOTSUP != EOPNOTSUPP
[EOPNOTSUPP] = "-EOPNOTSUPP",
#endif
};
const char *tiny_strerror(int errnum)
{
/* dark magic: All error strings start with a "-". For positive error codes
* an offset of 1 is added to the address of the string, jumping one char
* behind the "-". This way the strings do not have to be allocated twice
* (once with and once without minus char).
*/
const char *retval = "-unknown";
unsigned offset = 1;
if (errnum <= 0) {
offset = 0;
errnum = -errnum;
}
if (((unsigned)errnum < ARRAY_SIZE(lookup))
&& (lookup[(unsigned)errnum] != NULL)) {
retval = lookup[(unsigned)errnum];
}
return retval + offset;
}
#if IS_USED(MODULE_TINY_STRERROR_AS_STRERROR)
__attribute__((alias("tiny_strerror"))) const char *__wrap_strerror(int errnum);
#endif
/** @} */

View File

@ -1,3 +1,8 @@
BOARD_INSUFFICIENT_MEMORY := \
arduino-duemilanove \
arduino-nano \
arduino-uno \
atmega328p \
atmega328p-xplained-mini \
nucleo-l011k4 \
#

View File

@ -42,12 +42,7 @@ int main(void)
do {
retval = hsc_init(&dev, &hsc_params[0]);
if (retval < 0) {
if (IS_USED(MODULE_NEWLIB) || IS_USED(MODULE_PICOLIBC)) {
printf("Initialization error with code: %s\n", strerror(-retval));
}
else {
puts("Initialization failed");
}
printf("Initialization error with code: %s\n", strerror(-retval));
}
xtimer_usleep(SLEEP_USEC);
} while (retval);