#include <ggi/gg.h> size_t ggstrlcpy(char *dst, const char *src, size_t siz); size_t ggstrlcat(char *dst, const char *src, size_t siz);
The ggstrlcpy function copies up to siz - 1 characters from the NUL-terminated string src to dst, NUL-terminating the result.
The ggstrlcat function appends the NUL-terminated string src to the end of dst. It will append at most siz - strlen(dst) - 1 bytes, NUL-terminating the result.
Note however, that if ggstrlcat 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 ggstrlcat 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.
char *s, *p, buf[BUFSIZ]; ... (void)ggstrlcpy(buf, s, sizeof(buf)); (void)ggstrlcat(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 (ggstrlcpy(pname, dir, sizeof(pname)) >= sizeof(pname))
goto toolong;
if (ggstrlcat(pname, file, sizeof(pname)) >= sizeof(pname))
goto toolong;
Since we know how many characters we copied the first time, we can speed things up a bit by using a copy instead of an append:
char *dir, *file, pname[MAXPATHLEN];
size_t n;
...
n = ggstrlcpy(pname, dir, sizeof(pname));
if (n >= sizeof(pname))
goto toolong;
if (ggstrlcpy(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 ggstrlcpy and ggstrlcat.