[klibc] [PATCH 1/3] klibc: Add scandir() and alphasort() support.

Mike Waychison mikew at google.com
Mon Aug 1 09:53:10 PDT 2011


Looks like I forgot to add the cover sheet that I wrote up for this
series that actually explains why I'm doing this.  Here it is:


This patchset applies to klibc mainline.

This patchset introduces the ability to kinit to execute scripts or
executable files present in in the initramfs before switching over to
the root filesystem.

It is implemented by first implementing scandir() and alphasort() as
present in POSIX.1-2008 in klibc itself, and then using that as the
basis for iterating and executing files via a run_scripts() call.

This patchset introduces two different drop directories, though this is
of course subject to change and these are only presented in an effort to
put an example forward.  I currently only have a requirement to run
stuff between the time we call do_mounts() and the time we call
run_init().

These are the directories:

      /scripts/after-network: ipconfig is completed, but the root
          filesystem isn't yet mounted.
      /scripts/after-mount: the root filesystem has just been mounted at
          /root.

I believe this would help both our use-case (where we'd like to do
customization of the early-bootup sequence without having to hack kinit
too much), and the use case for initramfs-tools, opening the door to
replace all the "core" shell there kinit as a C implementation.

Thanks,

Mike Waychison

Related discussions
===================
    - We recently had a discussion at:

      http://www.zytor.com/pipermail/klibc/2011-July/003014.html

      where I wanted to refactor bits of kinit out so that I could
      invoke them from a shell script.  This patchset is an alternative
      solution that would allow users of kinit to add custom logic at
      the intermediate stages without having to have the whole init
      driven by a shell script.

Patchset summary
================

klibc: Add scandir() and alphasort() support.
kinit: Add run_scripts()
kinit: Add callsites to execute files in drop-directories.



On Fri, Jul 29, 2011 at 2:37 PM, Mike Waychison <mikew at google.com> wrote:
> Add support for scandir() and alphasort() as defined in POSIX.1-2008.
>
> Signed-off-by: Mike Waychison <mikew at google.com>
> ---
>  usr/include/dirent.h |    7 +++++
>  usr/klibc/Kbuild     |    2 +
>  usr/klibc/scandir.c  |   76 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 84 insertions(+), 1 deletions(-)
>  create mode 100644 usr/klibc/scandir.c
>
> diff --git a/usr/include/dirent.h b/usr/include/dirent.h
> index e324474..3b1ff59 100644
> --- a/usr/include/dirent.h
> +++ b/usr/include/dirent.h
> @@ -30,4 +30,11 @@ static __inline__ int dirfd(DIR * __d)
>        return __d->__fd;
>  }
>
> +__extern int scandir(const char *dirp, struct dirent ***namelist,
> +                    int (*filter)(const struct dirent *),
> +                    int (*compar)(const struct dirent **,
> +                                  const struct dirent **));
> +
> +int alphasort(const struct dirent **a, const struct dirent **b);
> +
>  #endif                         /* _DIRENT_H */
> diff --git a/usr/klibc/Kbuild b/usr/klibc/Kbuild
> index af40367..40e61da 100644
> --- a/usr/klibc/Kbuild
> +++ b/usr/klibc/Kbuild
> @@ -42,7 +42,7 @@ klib-y := vsnprintf.o snprintf.o vsprintf.o sprintf.o \
>          seteuid.o setegid.o \
>          getenv.o setenv.o putenv.o __put_env.o unsetenv.o \
>          clearenv.o nullenv.o \
> -         getopt.o getopt_long.o readdir.o remove.o \
> +         getopt.o getopt_long.o readdir.o scandir.o remove.o \
>          syslog.o closelog.o pty.o getpt.o posix_openpt.o isatty.o reboot.o \
>          time.o utime.o llseek.o nice.o getpriority.o \
>          qsort.o bsearch.o \
> diff --git a/usr/klibc/scandir.c b/usr/klibc/scandir.c
> new file mode 100644
> index 0000000..1f58b15
> --- /dev/null
> +++ b/usr/klibc/scandir.c
> @@ -0,0 +1,76 @@
> +/*
> + * scandir.c: scandir/alphasort
> + */
> +
> +#include <stdlib.h>
> +#include <string.h>
> +#include <errno.h>
> +
> +#include <dirent.h>
> +
> +int scandir(const char *dirp, struct dirent ***namelist,
> +           int (*filter)(const struct dirent *),
> +           int (*compar)(const struct dirent **, const struct dirent **))
> +{
> +       struct dirent **nl = NULL, **next_nl;
> +       struct dirent *dirent;
> +       size_t count = 0;
> +       size_t allocated = 0;
> +       DIR *dir;
> +
> +       dir = opendir(dirp);
> +       if (!dir)
> +               return -1;
> +
> +       while (1) {
> +               dirent = readdir(dir);
> +               if (!dirent)
> +                       break;
> +               if (!filter || filter(dirent)) {
> +                       struct dirent *copy;
> +                       copy = malloc(sizeof(*copy));
> +                       if (!copy)
> +                               goto cleanup_fail;
> +                       memcpy(copy, dirent, sizeof(*copy));
> +
> +                       /* Extend the array if needed */
> +                       if (count == allocated) {
> +                               if (allocated == 0)
> +                                       allocated = 15; /* ~1 page worth */
> +                               else
> +                                       allocated *= 2;
> +                               next_nl = realloc(nl, allocated);
> +                               if (!next_nl) {
> +                                       free(copy);
> +                                       goto cleanup_fail;
> +                               }
> +                               nl = next_nl;
> +                       }
> +
> +                       nl[count++] = copy;
> +               }
> +       }
> +
> +       qsort(nl, count, sizeof(struct dirent *),
> +             (int (*)(const void *, const void *))compar);
> +
> +       closedir(dir);
> +
> +       *namelist = nl;
> +       return count;
> +
> +cleanup_fail:
> +       while (count) {
> +               dirent = nl[--count];
> +               free(dirent);
> +       }
> +       free(nl);
> +       closedir(dir);
> +       errno = ENOMEM;
> +       return -1;
> +}
> +
> +int alphasort(const struct dirent **a, const struct dirent **b)
> +{
> +       return strcmp((*a)->d_name, (*b)->d_name);
> +}
>
>



More information about the klibc mailing list