author | Olivier Brunel
<jjk@jjacky.com> 2023-05-14 15:02:09 UTC |
committer | Olivier Brunel
<jjk@jjacky.com> 2023-07-05 07:37:02 UTC |
parent | e93f316e014aa0abe77d3896fc4181cb2d75b026 |
src/doc/direntry.h.0.md | +3 | -0 |
src/doc/direntry.h/sascandirat.3.md | +43 | -0 |
src/liblimb/direntry.h/sascandirat.c | +34 | -0 |
src/liblimb/djbunix.h/salsat.c | +11 | -40 |
src/liblimb/include/limb/direntry.h | +5 | -0 |
diff --git a/src/doc/direntry.h.0.md b/src/doc/direntry.h.0.md index 6935be2..bb27378 100644 --- a/src/doc/direntry.h.0.md +++ b/src/doc/direntry.h.0.md @@ -32,3 +32,6 @@ The following functions are defined : : [opendirat](3) :: Open a directory stream, with relative path to a given file descriptor + +: [sascandirat](3) +:: Scan a directory to fill a *stralloc*. diff --git a/src/doc/direntry.h/sascandirat.3.md b/src/doc/direntry.h/sascandirat.3.md new file mode 100644 index 0000000..0dc0ded --- /dev/null +++ b/src/doc/direntry.h/sascandirat.3.md @@ -0,0 +1,43 @@ +% limb manual +% sascandirat(3) + +# NAME + +sascandirat - scan a directory to fill a stralloc + +# SYNOPSIS + + #include <fcntl.h> /* AT_FDCWD */ + #include <limb/direntry.h> + +```pre hl +typedef ssize_t (*sascande) (stralloc *<em>sa</em>, direntry *<em>de</em>, int <em>dirfd</em>) + +int sascandirat(stralloc *<em>sa</em>, int <em>dirfd</em>, const char *<em>name</em>, sascande <em>fn</em>, size_t *<em>mlen</em>) +``` + +# DESCRIPTION + +The `sascandirat`() function scans the directory `name` calling the function +`fn` on each of its directory entry, save for `.` and `..` which are ignored. +Said function shall add relevant information regarding the directory entry +pointed by `de` into the stralloc pointed by `sa` and return the size added. It +may return zero to indicate the entry was ignored. On error, it should return -1 +and set `errno` to indicate the error. + +If `name` describes a relative path, it is relative to the directory associated +with the file descriptor `dirfd`, which may be *AT_FDCWD* to use the current +working directory. + +Once the entire directory has been scanned, if `mlen` is not *NULL* the pointed +value will be set to the maximum length returned by `fn`. + +# RETURN VALUE + +The function returns the number of entries for which data was added into `sa` on +success. Otherwise it returns -1 and sets `errno` to indicate the error. + +# ERRORS + +The function may fail and set `errno` for the error described for +[opendirat](3), [readdir](3), as well as those set by the function `fn`. diff --git a/src/liblimb/direntry.h/sascandirat.c b/src/liblimb/direntry.h/sascandirat.c new file mode 100644 index 0000000..082afab --- /dev/null +++ b/src/liblimb/direntry.h/sascandirat.c @@ -0,0 +1,34 @@ +/* This file is part of limb https://lila.oss/limb + * Copyright (C) 2023 Olivier Brunel jjk@jjacky.com */ +/* SPDX-License-Identifier: GPL-2.0-only */ +#include <errno.h> +#include <limb/direntry.h> + +int +sascandirat(stralloc *sa, int bfd, const char *name, sascande fn, size_t *mlen) +{ + size_t salen = sa->len; + size_t maxlen = 0; + int ret = 0; + DIR *dir = opendirat(bfd, name); + if (!dir) return -1; + + direntry *de; + while ((errno = 0, de = readdir(dir))) { + if (ISDOTDOT(de)) continue; + + ssize_t len = fn(sa, de, dirfd(dir)); + if (len < 0) break; + if ((size_t) len > maxlen) maxlen = len; + if (len) ++ret; + } + if (errno) { + ret = -1; + sa->len = salen; + } else if (mlen) { + *mlen = maxlen; + } + + dir_close(dir); + return ret; +} diff --git a/src/liblimb/djbunix.h/salsat.c b/src/liblimb/djbunix.h/salsat.c index ac5275d..fb8bbe6 100644 --- a/src/liblimb/djbunix.h/salsat.c +++ b/src/liblimb/djbunix.h/salsat.c @@ -2,50 +2,21 @@ * Copyright (C) 2023 Olivier Brunel jjk@jjacky.com */ /* SPDX-License-Identifier: GPL-2.0-only */ #include <errno.h> -#include <dirent.h> #include <limb/direntry.h> #include <limb/djbunix.h> +#include <limb/gccattributes.h> + +static ssize_t +sascandir_name(stralloc *sa, direntry *de, int bfd gccattr_unused) +{ + size_t len = strlen(de->d_name); + if (!stralloc_catb(sa, de->d_name, len + 1)) + return -1; + return len; +} int salsat(int fd, const char *name, stralloc *sa, size_t *mlen) { - size_t salen = sa->len; - size_t maxlen = 0; - int ret = 0; - DIR *dir = opendirat(fd, name); - - if (!dir) - return (errno == ENOENT) ? 0 : -1; - - for (;;) - { - direntry *de; - - errno = 0; - de = readdir(dir); - if (!de) - break; - - if (de->d_name[0] == '.') { - if (!de->d_name[1] || (de->d_name[1] == '.' && !de->d_name[2])) - continue; - } - - size_t len = strlen(de->d_name); - if (len > maxlen) - maxlen = len; - - if (!stralloc_catb(sa, de->d_name, len + 1)) - break; - - ++ret; - } - if (errno) { - ret = -1; - sa->len = salen; - } else if (mlen) - *mlen = maxlen; - - dir_close(dir); - return ret; + return sascandirat(sa, fd, name, sascandir_name, mlen); } diff --git a/src/liblimb/include/limb/direntry.h b/src/liblimb/include/limb/direntry.h index cfcfdbc..76f00e8 100644 --- a/src/liblimb/include/limb/direntry.h +++ b/src/liblimb/include/limb/direntry.h @@ -5,9 +5,14 @@ #define LIMB_DIRENTRY_H #include <skalibs/direntry.h> +#include <skalibs/stralloc.h> + +typedef ssize_t (*sascande) (stralloc *sa, direntry *de, int bfd); #define ISDOTDOT(de) ((de)->d_name[0] == '.' && (!(de)->d_name[1] || ((de)->d_name[1] == '.' && !(de)->d_name[2]))) extern DIR *opendirat(int bfd, const char *name); +extern int sascandirat(stralloc *sa, int bfd, const char *name, sascande fn, size_t *mlen); + #endif /* LIMB_DIRENTRY_H */