Especially since these functions' return values make it hard to use them to step forward in the buffer, so subsequent calls need to walk over the already-inserted characters again and again. That kind of redundant work makes me grit my teeth, which I guess is a sign that I'm a C programmer at heart. :)
Compare:
char buf[1024];
snprintf(buf, sizeof buf, "%s%s", "foo", "bar");
and char buf[1024];
strcpy(buf, "foo");
strlcat(buf, "bar", sizeof buf);
The latter is given a pointer to the base buffer, so it has to walk past the existing characters in order to find the end where the concatenation should start.I also find the "size" arguments confusing and weird. I think it's idiomatic in C to (tightly) associate a size with a buffer pointer, and speaking in terms of "there are n bytes available at this location" makes sense to me. So the prototype really should have been
size_t strlcat_unwind(char *buf, size_t buf_size, const char *src);