From: Yu Watanabe Date: Mon, 13 Dec 2021 22:33:53 +0000 (+0900) Subject: util: introduce strnpcpy_full() and friends to provide whether result is truncated... X-Git-Tag: v251-rc1~647^2~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e70151c94d1cd0e202cef44e62d8eb858d3703ab;p=thirdparty%2Fsystemd.git util: introduce strnpcpy_full() and friends to provide whether result is truncated or not --- diff --git a/src/basic/strxcpyx.c b/src/basic/strxcpyx.c index dbbf7d08d21..52b95650cf3 100644 --- a/src/basic/strxcpyx.c +++ b/src/basic/strxcpyx.c @@ -15,57 +15,73 @@ #include #include +#include "string-util.h" #include "strxcpyx.h" -size_t strnpcpy(char **dest, size_t size, const char *src, size_t len) { +size_t strnpcpy_full(char **dest, size_t size, const char *src, size_t len, bool *ret_truncated) { + bool truncated = false; + assert(dest); assert(src); - if (size == 0) + if (size == 0) { + if (ret_truncated) + *ret_truncated = len > 0; return 0; + } if (len >= size) { if (size > 1) *dest = mempcpy(*dest, src, size-1); size = 0; + truncated = true; } else if (len > 0) { *dest = mempcpy(*dest, src, len); size -= len; } + if (ret_truncated) + *ret_truncated = truncated; + *dest[0] = '\0'; return size; } -size_t strpcpy(char **dest, size_t size, const char *src) { +size_t strpcpy_full(char **dest, size_t size, const char *src, bool *ret_truncated) { assert(dest); assert(src); - return strnpcpy(dest, size, src, strlen(src)); + return strnpcpy_full(dest, size, src, strlen(src), ret_truncated); } -size_t strpcpyf(char **dest, size_t size, const char *src, ...) { +size_t strpcpyf_full(char **dest, size_t size, bool *ret_truncated, const char *src, ...) { + bool truncated = false; va_list va; int i; assert(dest); assert(src); - if (size == 0) - return 0; - va_start(va, src); i = vsnprintf(*dest, size, src, va); - if (i < (int)size) { + va_end(va); + + if (i < (int) size) { *dest += i; size -= i; - } else + } else { size = 0; - va_end(va); + truncated = i > 0; + } + + if (ret_truncated) + *ret_truncated = truncated; + return size; } -size_t strpcpyl(char **dest, size_t size, const char *src, ...) { +size_t strpcpyl_full(char **dest, size_t size, bool *ret_truncated, const char *src, ...) { + bool truncated = false; va_list va; assert(dest); @@ -73,31 +89,38 @@ size_t strpcpyl(char **dest, size_t size, const char *src, ...) { va_start(va, src); do { - size = strpcpy(dest, size, src); + bool t; + + size = strpcpy_full(dest, size, src, &t); + truncated = truncated || t; src = va_arg(va, char *); } while (src); va_end(va); + + if (ret_truncated) + *ret_truncated = truncated; return size; } -size_t strnscpy(char *dest, size_t size, const char *src, size_t len) { +size_t strnscpy_full(char *dest, size_t size, const char *src, size_t len, bool *ret_truncated) { char *s; assert(dest); assert(src); s = dest; - return strnpcpy(&s, size, src, len); + return strnpcpy_full(&s, size, src, len, ret_truncated); } -size_t strscpy(char *dest, size_t size, const char *src) { +size_t strscpy_full(char *dest, size_t size, const char *src, bool *ret_truncated) { assert(dest); assert(src); - return strnscpy(dest, size, src, strlen(src)); + return strnscpy_full(dest, size, src, strlen(src), ret_truncated); } -size_t strscpyl(char *dest, size_t size, const char *src, ...) { +size_t strscpyl_full(char *dest, size_t size, bool *ret_truncated, const char *src, ...) { + bool truncated = false; va_list va; char *s; @@ -107,10 +130,16 @@ size_t strscpyl(char *dest, size_t size, const char *src, ...) { va_start(va, src); s = dest; do { - size = strpcpy(&s, size, src); + bool t; + + size = strpcpy_full(&s, size, src, &t); + truncated = truncated || t; src = va_arg(va, char *); } while (src); va_end(va); + if (ret_truncated) + *ret_truncated = truncated; + return size; } diff --git a/src/basic/strxcpyx.h b/src/basic/strxcpyx.h index cdef492db10..4a648ed033b 100644 --- a/src/basic/strxcpyx.h +++ b/src/basic/strxcpyx.h @@ -1,14 +1,33 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once +#include #include #include "macro.h" -size_t strnpcpy(char **dest, size_t size, const char *src, size_t len); -size_t strpcpy(char **dest, size_t size, const char *src); -size_t strpcpyf(char **dest, size_t size, const char *src, ...) _printf_(3, 4); -size_t strpcpyl(char **dest, size_t size, const char *src, ...) _sentinel_; -size_t strnscpy(char *dest, size_t size, const char *src, size_t len); -size_t strscpy(char *dest, size_t size, const char *src); -size_t strscpyl(char *dest, size_t size, const char *src, ...) _sentinel_; +size_t strnpcpy_full(char **dest, size_t size, const char *src, size_t len, bool *ret_truncated); +static inline size_t strnpcpy(char **dest, size_t size, const char *src, size_t len) { + return strnpcpy_full(dest, size, src, len, NULL); +} +size_t strpcpy_full(char **dest, size_t size, const char *src, bool *ret_truncated); +static inline size_t strpcpy(char **dest, size_t size, const char *src) { + return strpcpy_full(dest, size, src, NULL); +} +size_t strpcpyf_full(char **dest, size_t size, bool *ret_truncated, const char *src, ...) _printf_(4, 5); +#define strpcpyf(dest, size, src, ...) \ + strpcpyf_full((dest), (size), NULL, (src), ##__VA_ARGS__) +size_t strpcpyl_full(char **dest, size_t size, bool *ret_truncated, const char *src, ...) _sentinel_; +#define strpcpyl(dest, size, src, ...) \ + strpcpyl_full((dest), (size), NULL, (src), ##__VA_ARGS__) +size_t strnscpy_full(char *dest, size_t size, const char *src, size_t len, bool *ret_truncated); +static inline size_t strnscpy(char *dest, size_t size, const char *src, size_t len) { + return strnscpy_full(dest, size, src, len, NULL); +} +size_t strscpy_full(char *dest, size_t size, const char *src, bool *ret_truncated); +static inline size_t strscpy(char *dest, size_t size, const char *src) { + return strscpy_full(dest, size, src, NULL); +} +size_t strscpyl_full(char *dest, size_t size, bool *ret_truncated, const char *src, ...) _sentinel_; +#define strscpyl(dest, size, src, ...) \ + strscpyl_full(dest, size, NULL, src, ##__VA_ARGS__)