author | Olivier Brunel
<jjk@jjacky.com> 2023-02-28 09:03:10 UTC |
committer | Olivier Brunel
<jjk@jjacky.com> 2023-02-28 09:25:54 UTC |
parent | 1613caef547c935d4d33d8022bd4e46a356d6b2c |
doc/salsat.3.md | +52 | -0 |
include/limb/djbunix.h | +4 | -0 |
meta/libs/limb | +1 | -0 |
src/salsat.c | +48 | -0 |
diff --git a/doc/salsat.3.md b/doc/salsat.3.md new file mode 100644 index 0000000..709c966 --- /dev/null +++ b/doc/salsat.3.md @@ -0,0 +1,52 @@ +% limb manual +% salsat(3) + +# NAME + +salsat, salst, salstat - append directory listing into an stralloc + +# SYNOPSIS + + #include <limb/djbunix.h> + +```pre hl +int salsat(int <em>fd</em>, const char *<em>name</em>, stralloc *<em>sa</em>, size_t *<em>maxlen</em>) + +int salst(stralloc *<em>sa</em>, const char *<em>name</em>, size_t *<em>maxlen</em>) +int salstat(stralloc *<em>sa</em>, int <em>fd</em>, const char *<em>name</em>, size_t *<em>maxlen</em>) +``` + +# DESCRIPTION + +The `salsat`() function appends the names of all files (except for `.` and `..`) +in directory `name` into the specified stralloc `sa` as NUL-terminated strings. + +It is the equivalent to [sals](3) function except when `name` specifies a +relative path, the directory to be opened is then determined relative to the +directory associated with the file descriptor `fd` instead of the current +working directory. + +If not NULL, `maxlen` will be set to the length of the longest file name added. +(It will be 0 in case of empty directory.) + +`salst`() is a macro to [sals](3) with a slightly different interface, namely +the stralloc `sa` as first argument. + +Similarly, `salstat`() is a macro to [salsat](3) with a slightly different +interface as well. + +# RETURN VALUE + +Upon successful completion, the `salsat` functions returns the number of names +added into `sa`. Otherwise, it returns -1 and sets `errno` to indicate the +error. + +# ERRORS + +The `salsat`() function may fail if : + +: *ENOMEM* +:: Out of memory to add names into `sa` + +It may also fail and set errno for any of the errors specified for the +functions [opendirat](3) and [readdir](3). diff --git a/include/limb/djbunix.h b/include/limb/djbunix.h index 7c67b6f..54423f2 100644 --- a/include/limb/djbunix.h +++ b/include/limb/djbunix.h @@ -3,6 +3,10 @@ #include <skalibs/stralloc.h> +extern int salsat(int fd, const char *name, stralloc *sa, size_t *maxlen); extern int sareadlinkat(stralloc *sa, int fd, const char * restrict file); +#define salst(sa,name,maxlen) sals(name, sa,maxlen) +#define salstat(sa,fd,name,maxlen) salsat(fd, name, sa, maxlen) + #endif /* LIMB_DJBUNIX_H */ diff --git a/meta/libs/limb b/meta/libs/limb index 7883419..afdaa12 100644 --- a/meta/libs/limb +++ b/meta/libs/limb @@ -8,6 +8,7 @@ obj/open_exclat.o # direntry.h obj/opendirat.o # djbunix.h +obj/salsat.o obj/sareadlinkat.o # buffer.h obj/buffer_putescall.o diff --git a/src/salsat.c b/src/salsat.c new file mode 100644 index 0000000..c334b84 --- /dev/null +++ b/src/salsat.c @@ -0,0 +1,48 @@ +#include <errno.h> +#include <dirent.h> +#include "limb/direntry.h" +#include "limb/djbunix.h" + +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; +}