From: Ralph Corderoy Date: Sun, 30 Oct 2016 13:45:40 +0000 (+0000) Subject: Add trunccpy(), and the convenience TRUNCCPY(). X-Git-Url: https://diplodocus.org/git/nmh/commitdiff_plain/603cc061a9c1fa18ab765024491aeeda18686901?ds=sidebyside Add trunccpy(), and the convenience TRUNCCPY(). truncpy copies at most size - 1 chars from non-NULL src to non-NULL dst, and ensures dst is NUL terminated. If size is zero then it aborts as dst cannot be NUL terminated. It's to be used when truncation is intended and correct, e.g. reporting a possibly very long external string back to the user. One of its advantages over strncpy(3) is it doesn't pad in the common case of no truncation. --- diff --git a/h/utils.h b/h/utils.h index fe054931..939bd80e 100644 --- a/h/utils.h +++ b/h/utils.h @@ -63,6 +63,10 @@ char *find_str (const char [], size_t, const char *); char *rfind_str (const char [], size_t, const char *); char *nmh_strcasestr (const char *, const char *); +void trunccpy(char *dst, const char *src, size_t size); +/* A convenience for the common case of dst being an array. */ +#define TRUNCCPY(dst, src) trunccpy(dst, src, sizeof (dst)) + bool HasPrefix(const char *s, const char *prefix); bool HasSuffix(const char *s, const char *suffix); bool HasSuffixC(const char *s, int c); diff --git a/sbr/utils.c b/sbr/utils.c index ff144673..ca809439 100644 --- a/sbr/utils.c +++ b/sbr/utils.c @@ -346,6 +346,31 @@ nmh_strcasestr (const char *s1, const char *s2) { } +/* truncpy copies at most size - 1 chars from non-NULL src to non-NULL + * dst, and ensures dst is NUL terminated. If size is zero then it + * aborts as dst cannot be NUL terminated. + * + * It's to be used when truncation is intended and correct, e.g. + * reporting a possibly very long external string back to the user. One + * of its advantages over strncpy(3) is it doesn't pad in the common + * case of no truncation. */ +void trunccpy(char *dst, const char *src, size_t size) +{ + if (!size) { + advise(NULL, "trunccpy: zero-length destination: \"%.20s\"", + src ? src : "null"); + abort(); + } + + if (strnlen(src, size) < size) { + strcpy(dst, src); + } else { + memcpy(dst, src, size - 1); + dst[size - 1] = '\0'; + } +} + + /* HasPrefix returns true if non-NULL s starts with non-NULL prefix. */ bool HasPrefix(const char *s, const char *prefix) {