xref: /netbsd-src/common/lib/libc/string/strlcat.c (revision 2dd10e69e37fb0959c0d785c93ea18efddb585bb)
1*2dd10e69Sriastradh /*	$NetBSD: strlcat.c,v 1.5 2024/11/01 21:11:37 riastradh Exp $	*/
237c9f0a6Schristos /*	$OpenBSD: strlcat.c,v 1.10 2003/04/12 21:56:39 millert Exp $	*/
337c9f0a6Schristos 
437c9f0a6Schristos /*
537c9f0a6Schristos  * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
637c9f0a6Schristos  *
737c9f0a6Schristos  * Permission to use, copy, modify, and distribute this software for any
837c9f0a6Schristos  * purpose with or without fee is hereby granted, provided that the above
937c9f0a6Schristos  * copyright notice and this permission notice appear in all copies.
1037c9f0a6Schristos  *
1137c9f0a6Schristos  * THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL
1237c9f0a6Schristos  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
1337c9f0a6Schristos  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE
1437c9f0a6Schristos  * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1537c9f0a6Schristos  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
1637c9f0a6Schristos  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
1737c9f0a6Schristos  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1837c9f0a6Schristos  */
1937c9f0a6Schristos 
2037c9f0a6Schristos #if !defined(_KERNEL) && !defined(_STANDALONE)
2137c9f0a6Schristos #if HAVE_NBTOOL_CONFIG_H
2237c9f0a6Schristos #include "nbtool_config.h"
2337c9f0a6Schristos #endif
2437c9f0a6Schristos 
2537c9f0a6Schristos #include <sys/cdefs.h>
2637c9f0a6Schristos #if defined(LIBC_SCCS) && !defined(lint)
27*2dd10e69Sriastradh __RCSID("$NetBSD: strlcat.c,v 1.5 2024/11/01 21:11:37 riastradh Exp $");
2837c9f0a6Schristos #endif /* LIBC_SCCS and not lint */
2937c9f0a6Schristos 
3037c9f0a6Schristos #ifdef _LIBC
3137c9f0a6Schristos #include "namespace.h"
3237c9f0a6Schristos #endif
3337c9f0a6Schristos #include <sys/types.h>
3437c9f0a6Schristos #include <assert.h>
3537c9f0a6Schristos #include <string.h>
3637c9f0a6Schristos 
3737c9f0a6Schristos #ifdef _LIBC
3837c9f0a6Schristos # ifdef __weak_alias
3937c9f0a6Schristos __weak_alias(strlcat, _strlcat)
4037c9f0a6Schristos # endif
4137c9f0a6Schristos #endif
4237c9f0a6Schristos 
4337c9f0a6Schristos #else
4437c9f0a6Schristos #include <lib/libkern/libkern.h>
4537c9f0a6Schristos #endif /* !_KERNEL && !_STANDALONE */
4637c9f0a6Schristos 
4737c9f0a6Schristos #if !HAVE_STRLCAT
4837c9f0a6Schristos /*
4937c9f0a6Schristos  * Appends src to string dst of size siz (unlike strncat, siz is the
5037c9f0a6Schristos  * full size of dst, not space left).  At most siz-1 characters
5137c9f0a6Schristos  * will be copied.  Always NUL terminates (unless siz <= strlen(dst)).
5237c9f0a6Schristos  * Returns strlen(src) + MIN(siz, strlen(initial dst)).
5337c9f0a6Schristos  * If retval >= siz, truncation occurred.
5437c9f0a6Schristos  */
5537c9f0a6Schristos size_t
56*2dd10e69Sriastradh strlcat(char *__restrict dst, const char *__restrict src, size_t siz)
5737c9f0a6Schristos {
58cd7877ebSmatt #if 1
5937c9f0a6Schristos 	char *d = dst;
6037c9f0a6Schristos 	const char *s = src;
6137c9f0a6Schristos 	size_t n = siz;
6237c9f0a6Schristos 	size_t dlen;
6337c9f0a6Schristos 
6437c9f0a6Schristos 	_DIAGASSERT(dst != NULL);
6537c9f0a6Schristos 	_DIAGASSERT(src != NULL);
6637c9f0a6Schristos 
6737c9f0a6Schristos 	/* Find the end of dst and adjust bytes left but don't go past end */
6837c9f0a6Schristos 	while (n-- != 0 && *d != '\0')
6937c9f0a6Schristos 		d++;
7037c9f0a6Schristos 	dlen = d - dst;
7137c9f0a6Schristos 	n = siz - dlen;
7237c9f0a6Schristos 
7337c9f0a6Schristos 	if (n == 0)
7437c9f0a6Schristos 		return(dlen + strlen(s));
7537c9f0a6Schristos 	while (*s != '\0') {
7637c9f0a6Schristos 		if (n != 1) {
7737c9f0a6Schristos 			*d++ = *s;
7837c9f0a6Schristos 			n--;
7937c9f0a6Schristos 		}
8037c9f0a6Schristos 		s++;
8137c9f0a6Schristos 	}
8237c9f0a6Schristos 	*d = '\0';
8337c9f0a6Schristos 
8437c9f0a6Schristos 	return(dlen + (s - src));	/* count does not include NUL */
85cd7877ebSmatt #else
86cd7877ebSmatt 	_DIAGASSERT(dst != NULL);
87cd7877ebSmatt 	_DIAGASSERT(src != NULL);
88cd7877ebSmatt 
89cd7877ebSmatt 	/*
90cd7877ebSmatt 	 * Find length of string in dst (maxing out at siz).
91cd7877ebSmatt 	 */
92cd7877ebSmatt 	size_t dlen = strnlen(dst, siz);
93cd7877ebSmatt 
94cd7877ebSmatt 	/*
95cd7877ebSmatt 	 * Copy src into any remaining space in dst (truncating if needed).
96cd7877ebSmatt 	 * Note strlcpy(dst, src, 0) returns strlen(src).
97cd7877ebSmatt 	 */
98cd7877ebSmatt 	return dlen + strlcpy(dst + dlen, src, siz - dlen);
99cd7877ebSmatt #endif
10037c9f0a6Schristos }
10137c9f0a6Schristos #endif
102