xref: /illumos-gate/usr/src/lib/libc/port/i18n/wcslcat.c (revision 4c75c86ed9514c627ddb82a345adecc7c1e43b91)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2025 Oxide Computer Company
14  */
15 
16 /*
17  * Wide character version of strlcat(3C). This appends up to dstlen - 1 wide
18  * characters to dst, taking into account any string that already is present
19  * there. The resulting string is always terminated with a NULL wide-character
20  * unless the dst buffer is already full of data with no terminator. The number
21  * of wide characters that would be in the fully concatenated string is
22  * returned.
23  */
24 
25 #include "lint.h"
26 #include <wchar.h>
27 #include <sys/sysmacros.h>
28 
29 size_t
30 wcslcat(wchar_t *restrict dst, const wchar_t *restrict src, size_t dstlen)
31 {
32 	size_t srclen = wcslen(src);
33 	size_t dstoff = wcsnlen(dst, dstlen);
34 	size_t nwcs;
35 
36 	/*
37 	 * If there is no space in the destination buffer for the source string,
38 	 * then do not do anything. We check both for the case where there is no
39 	 * valid NUL in dst (dstoff == dstlen) or where there is one, which
40 	 * means that there is nothing to actually copy. It's also possible that
41 	 * there was never any space to begin with.
42 	 */
43 	if (dstlen == 0 || dstoff >= dstlen - 1) {
44 		return (srclen + dstoff);
45 	}
46 
47 	nwcs = MIN(dstlen - 1 - dstoff, srclen);
48 	(void) wmemcpy(dst + dstoff, src, nwcs);
49 	dst[nwcs + dstoff] = L'\0';
50 	return (srclen + dstoff);
51 }
52