Hi, This is in preparation to moving tar(1) over to recurse() instead of ftw().
The caller of recurse() doesn't need to prepare a full path manually anymore. cheers, sin
>From 0697ac3a64dca3f4a3857784f1e1a15dd82827ee Mon Sep 17 00:00:00 2001 From: sin <s...@2f30.org> Date: Thu, 30 Jan 2014 12:37:35 +0000 Subject: [PATCH] Add strlcpy()/strlcat() Refactor recurse() routine in preparation to moving tar(1) over to use it instead of the ftw() interface. --- Makefile | 4 +++- util.h | 4 +++- util/recurse.c | 30 ++++++++++++++++-------------- util/strlcat.c | 35 +++++++++++++++++++++++++++++++++++ util/strlcpy.c | 31 +++++++++++++++++++++++++++++++ 5 files changed, 88 insertions(+), 16 deletions(-) create mode 100644 util/strlcat.c create mode 100644 util/strlcpy.c diff --git a/Makefile b/Makefile index 9fada0f..204e05c 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,9 @@ LIB = \ util/rm.o \ util/sha1.o \ util/sha256.o \ - util/sha512.o + util/sha512.o \ + util/strlcat.o \ + util/strlcpy.o SRC = \ basename.c \ diff --git a/util.h b/util.h index f7e8780..4856bb3 100644 --- a/util.h +++ b/util.h @@ -1,5 +1,5 @@ /* See LICENSE file for copyright and license details. */ - +#include <stddef.h> #include "arg.h" #define UTF8_POINT(c) (((c) & 0xc0) != 0x80) @@ -20,4 +20,6 @@ long estrtol(const char *, int); void fnck(const char *, const char *, int (*)(const char *, const char *)); void putword(const char *); void recurse(const char *, void (*)(const char *)); +size_t strlcat(char *, const char *, size_t); +size_t strlcpy(char *, const char *, size_t); void weprintf(const char *, ...); diff --git a/util/recurse.c b/util/recurse.c index b3d1f8c..6ac235e 100644 --- a/util/recurse.c +++ b/util/recurse.c @@ -1,17 +1,19 @@ /* See LICENSE file for copyright and license details. */ #include <dirent.h> -#include <errno.h> +#include <limits.h> +#include <stdio.h> #include <stdlib.h> #include <string.h> -#include <unistd.h> #include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> #include "../util.h" void recurse(const char *path, void (*fn)(const char *)) { - char *cwd; + char buf[PATH_MAX], *p; struct dirent *d; struct stat st; DIR *dp; @@ -22,19 +24,19 @@ recurse(const char *path, void (*fn)(const char *)) eprintf("opendir %s:", path); } - cwd = agetcwd(); - if(chdir(path) == -1) - eprintf("chdir %s:", path); - while((d = readdir(dp))) { - if(strcmp(d->d_name, ".") && strcmp(d->d_name, "..")) - fn(d->d_name); + if (strcmp(d->d_name, ".") == 0 || + strcmp(d->d_name, "..") == 0) + continue; + strlcpy(buf, path, sizeof(buf)); + p = strrchr(buf, '\0'); + /* remove all trailing slashes */ + while (--p >= buf && *p == '/') *p ='\0'; + strlcat(buf, "/", sizeof(buf)); + if (strlcat(buf, d->d_name, sizeof(buf)) >= sizeof(buf)) + enprintf(EXIT_FAILURE, "path too long\n"); + fn(buf); } closedir(dp); - if(chdir(cwd) == -1) - eprintf("chdir %s:", cwd); - - free(cwd); } - diff --git a/util/strlcat.c b/util/strlcat.c new file mode 100644 index 0000000..a50c612 --- /dev/null +++ b/util/strlcat.c @@ -0,0 +1,35 @@ +/* Taken from OpenBSD */ +#include <sys/types.h> +#include <string.h> + +/* + * Appends src to string dst of size siz (unlike strncat, siz is the + * full size of dst, not space left). At most siz-1 characters + * will be copied. Always NUL terminates (unless siz <= strlen(dst)). + * Returns strlen(src) + MIN(siz, strlen(initial dst)). + * If retval >= siz, truncation occurred. + */ +size_t +strlcat(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + size_t dlen; + /* Find the end of dst and adjust bytes left but don't go past end */ + while (n-- != 0 && *d != '\0') + d++; + dlen = d - dst; + n = siz - dlen; + if (n == 0) + return(dlen + strlen(s)); + while (*s != '\0') { + if (n != 1) { + *d++ = *s; + n--; + } + s++; + } + *d = '\0'; + return(dlen + (s - src)); /* count does not include NUL */ +} diff --git a/util/strlcpy.c b/util/strlcpy.c new file mode 100644 index 0000000..3779c78 --- /dev/null +++ b/util/strlcpy.c @@ -0,0 +1,31 @@ +/* Taken from OpenBSD */ +#include <sys/types.h> +#include <string.h> + +/* + * Copy src to string dst of size siz. At most siz-1 characters + * will be copied. Always NUL terminates (unless siz == 0). + * Returns strlen(src); if retval >= siz, truncation occurred. + */ +size_t +strlcpy(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + /* Copy as many bytes as will fit */ + if (n != 0) { + while (--n != 0) { + if ((*d++ = *s++) == '\0') + break; + } + } + /* Not enough room in dst, add NUL and traverse rest of src */ + if (n == 0) { + if (siz != 0) + *d = '\0'; /* NUL-terminate dst */ + while (*s++) + ; + } + return(s - src - 1); /* count does not include NUL */ +} -- 1.8.5.3