Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

string: strerror_r() implementation #280

Merged
merged 1 commit into from
Aug 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions include/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@ extern size_t strcspn(const char *str1, const char *str2);
extern char *strerror(int errnum);


/* Thread-safe strerror. */
extern int strerror_r(int errnum, char *buf, size_t buflen);


/* Computes the length of the string str up to but not including the terminating null character. */
extern size_t strlen(const char *str);

Expand Down
58 changes: 47 additions & 11 deletions string/strerror.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>


Expand Down Expand Up @@ -44,7 +45,6 @@ static const errinfo_t gaitab[] = {
// static assert: 16-bit offset
static const char assert_errnames_size[-(sizeof(errnames) > 0xFFFF)] __attribute__((unused));
static const char assert_gainames_size[-(sizeof(gainames) > 0xFFFF)] __attribute__((unused));
static char err_unknownMsg[32]; /* FIXME: Make thread safe? IMHO overkill */


static int err_cmp(const void *key, const void *elem)
Expand All @@ -56,7 +56,7 @@ static int err_cmp(const void *key, const void *elem)
}


static inline const char *strerror_(const errinfo_t *tab, size_t tabsz, const char *names, int errnum)
static inline const char *strerror_(const errinfo_t *tab, size_t tabsz, const char *names, int errnum, char *buff, size_t bufflen, int *err)
{
const errinfo_t *e;

Expand All @@ -65,25 +65,61 @@ static inline const char *strerror_(const errinfo_t *tab, size_t tabsz, const ch
}

e = bsearch((void *)(long)errnum, tab, tabsz / sizeof(*tab), sizeof(*tab), err_cmp);

if (e == NULL) {
(void)sprintf(err_unknownMsg, "Unknown error %d", errnum);
errno = EINVAL;
return err_unknownMsg;
}
else {
return names + e->offset;
(void)snprintf(buff, bufflen, "Unknown error %d", errnum);
*err = EINVAL;
return buff;
}

return names + e->offset;
}


char *strerror(int errnum)
{
return (char *)strerror_(errtab, sizeof(errtab), errnames, errnum);
static char unknownMsg[32];
const char *str;
int err = 0;

str = strerror_(errtab, sizeof(errtab), errnames, errnum, unknownMsg, sizeof(unknownMsg), &err);
if (err != 0) {
errno = err;
}

return (char *)str;
}


int strerror_r(int errnum, char *buf, size_t buflen)
{
char unknownMsg[32];
const char *str;
int ret = 0;
size_t len;

str = strerror_(errtab, sizeof(errtab), errnames, errnum, unknownMsg, sizeof(unknownMsg), &ret);
len = strlen(str);
if (buflen > len) {
memcpy(buf, str, len + 1);
}
else {
ret = ERANGE;
}

return ret;
}


const char *gai_strerror(int errnum)
{
return strerror_(gaitab, sizeof(gaitab), gainames, errnum);
static char unknownMsg[32];
const char *str;
int err = 0;

str = strerror_(gaitab, sizeof(gaitab), gainames, errnum, unknownMsg, sizeof(unknownMsg), &err);
if (err != 0) {
errno = err;
}

return (char *)str;
}
Loading