feat(string): add BSD strlcpy/strlcat at level 2
Exact OpenBSD semantics: strlcpy returns strlen(src) and writes at most size-1 bytes plus NUL; strlcat returns dlen + strlen(src) with dlen = min(size, strlen(dst)) and never reads past size bytes in dst. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <[email protected]>
This commit is contained in:
@@ -0,0 +1,56 @@
|
|||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Append src to dst, NUL-terminating the result within size bytes.
|
||||||
|
* Return dlen + strlen(src), where dlen = min(size, strlen(dst)): the length
|
||||||
|
* the result would have had without truncation. dst is never read past
|
||||||
|
* size bytes. When size is 0 or dlen == size, nothing is written.
|
||||||
|
*/
|
||||||
|
size_t
|
||||||
|
strlcat(char *dst, const char *src, size_t size)
|
||||||
|
{
|
||||||
|
char *d;
|
||||||
|
const char *s;
|
||||||
|
size_t n;
|
||||||
|
size_t dlen;
|
||||||
|
|
||||||
|
d = dst;
|
||||||
|
s = src;
|
||||||
|
n = size;
|
||||||
|
|
||||||
|
/* Find the end of dst, stopping after at most size bytes. */
|
||||||
|
while (n != 0 && *d != '\0')
|
||||||
|
{
|
||||||
|
d++;
|
||||||
|
n--;
|
||||||
|
}
|
||||||
|
dlen = (size_t)(d - dst);
|
||||||
|
n = size - dlen;
|
||||||
|
|
||||||
|
if (n != 0)
|
||||||
|
{
|
||||||
|
/* Append as much of src as fits, leaving room for the NUL. */
|
||||||
|
while (*s != '\0')
|
||||||
|
{
|
||||||
|
if (n != 1)
|
||||||
|
{
|
||||||
|
*d++ = *s;
|
||||||
|
n--;
|
||||||
|
}
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
*d = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Count the unwritten remainder of src. */
|
||||||
|
while (*s != '\0')
|
||||||
|
{
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dlen + (size_t)(s - src);
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy src to dst, NUL-terminating the result, truncated to fit size bytes.
|
||||||
|
* Return strlen(src): the length of the string the call tried to create,
|
||||||
|
* independent of any truncation. When size is 0, nothing is written.
|
||||||
|
*/
|
||||||
|
size_t
|
||||||
|
strlcpy(char *dst, const char *src, size_t size)
|
||||||
|
{
|
||||||
|
const char *orig_src;
|
||||||
|
size_t nleft;
|
||||||
|
|
||||||
|
orig_src = src;
|
||||||
|
nleft = size;
|
||||||
|
|
||||||
|
/* Copy as many bytes as will fit, leaving room for the NUL. */
|
||||||
|
if (nleft != 0)
|
||||||
|
{
|
||||||
|
while (--nleft != 0)
|
||||||
|
{
|
||||||
|
*dst = *src;
|
||||||
|
if (*src == '\0')
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dst++;
|
||||||
|
src++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* No room for a NUL (or size was 0): NUL-terminate and measure src. */
|
||||||
|
if (nleft == 0)
|
||||||
|
{
|
||||||
|
if (size != 0)
|
||||||
|
{
|
||||||
|
*dst = '\0';
|
||||||
|
}
|
||||||
|
while (*src != '\0')
|
||||||
|
{
|
||||||
|
src++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* src ends at its NUL either way, so this is strlen(original src). */
|
||||||
|
return (size_t)(src - orig_src);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user