---
name: "strlcat"
section: "3bsd"
platform: "linux"
package: "libbsd"
version: "0.12.2-2"
release: "Arch Linux 2026-11-01"
platforms: ["linux"]
url: "https://new.carta.tech/strlcpy/3bsd"
---

# strlcat(3bsd)

size-bounded string copying and concatenation

Part of [strlcpy(3bsd)](/strlcpy/3bsd.md).

## NAME

**strlcpy**, **strlcat** – size-bounded string copying and concatenation

## LIBRARY

library “libbsd”

## SYNOPSIS

**#include \<string.h\>**

(See [libbsd(7)](/libbsd/7.md) for include usage.)

*size\_t*\

**strlcpy**(*char \*dst*, *const char \*src*, *size\_t size*);

*size\_t*\

**strlcat**(*char \*dst*, *const char \*src*, *size\_t size*);

## DESCRIPTION

The **strlcpy**() and **strlcat**() functions copy and concatenate strings respectively. They are designed to be safer, more consistent, and less error prone replacements for [strncpy(3)](/strncpy/3.md) and [strncat(3)](/strncat/3.md). Unlike those functions, **strlcpy**() and **strlcat**() take the full size of the buffer (not just the length) and guarantee to NUL-terminate the result (as long as *size* is larger than 0 or, in the case of **strlcat**(), as long as there is at least one byte free in *dst*). Note that a byte for the NUL should be included in *size*. Also note that **strlcpy**() and **strlcat**() only operate on true “C” strings. This means that for **strlcpy**() *src* must be NUL-terminated and for **strlcat**() both *src* and *dst* must be NUL-terminated.

The **strlcpy**() function copies up to *size* - 1 characters from the NUL-terminated string *src* to *dst*, NUL-terminating the result.

The **strlcat**() function appends the NUL-terminated string *src* to the end of *dst*. It will append at most *size* - strlen(dst) - 1 bytes, NUL-terminating the result.

## RETURN VALUES

The **strlcpy**() and **strlcat**() functions return the total length of the string they tried to create. For **strlcpy**() that means the length of *src*. For **strlcat**() that means the initial length of *dst* plus the length of *src*. While this may seem somewhat confusing, it was done to make truncation detection simple.

Note, however, that if **strlcat**() traverses *size* characters without finding a NUL, the length of the string is considered to be *size* and the destination string will not be NUL-terminated (since there was no space for the NUL). This keeps **strlcat**() from running off the end of a string. In practice this should not happen (as it means that either *size* is incorrect or that *dst* is not a proper “C” string). The check exists to prevent potential security problems in incorrect code.

## EXAMPLES

The following code fragment illustrates the simple case:

```
char *s, *p, buf[BUFSIZ];
...
(void)strlcpy(buf, s, sizeof(buf));
(void)strlcat(buf, p, sizeof(buf));
```

To detect truncation, perhaps while building a pathname, something like the following might be used:

```
char *dir, *file, pname[MAXPATHLEN];
...
if (strlcpy(pname, dir, sizeof(pname)) >= sizeof(pname))
	goto toolong;
if (strlcat(pname, file, sizeof(pname)) >= sizeof(pname))
	goto toolong;
```

Since it is known how many characters were copied the first time, things can be sped up a bit by using a copy instead of an append:

```
char *dir, *file, pname[MAXPATHLEN];
size_t n;
...
n = strlcpy(pname, dir, sizeof(pname));
if (n >= sizeof(pname))
	goto toolong;
if (strlcpy(pname + n, file, sizeof(pname) - n) >= sizeof(pname) - n)
	goto toolong;
```

However, one may question the validity of such optimizations, as they defeat the whole purpose of **strlcpy**() and **strlcat**(). As a matter of fact, the first version of this manual page got it wrong.

## SEE ALSO

[snprintf(3)](/snprintf/3.md), [strncat(3)](/strncat/3.md), [strncpy(3)](/strncpy/3.md)

## HISTORY

The **strlcpy**() and **strlcat**() functions first appeared in OpenBSD 2.4, and made their appearance in NetBSD 1.4.3, FreeBSD 3.3 and glibc 2.38.
