[lxc-devel] liblxc, lxc-browse()

Daniel Lezcano daniel.lezcano at free.fr
Tue May 3 22:16:23 UTC 2011


On 04/13/2011 07:49 PM, Francois-Xavier Bourlet wrote:
> Hi,
>
> Here's a patch with the purpose adding a way to browse containers trough liblxc.
> I added the function lxc-browse, that simply call back a function with
> the container name as parameter.
> It help to abstract how to browse containers without needed to know
> the underlaying structure of LXC.
>
> In case this path seem too big, at least something like the second
> path; that simply provide a way to retrieve LXCPATH; would be better
> than nothing, trough less abstracted.

Please in the future, inline the patches. One mail per patch, that will 
be easier to review.

Thanks.

> From 519012fa31068611096605447061bc90ffeef474 Mon Sep 17 00:00:00 2001
> From: =?UTF-8?q?Fran=C3=A7ois-Xavier=20Bourlet?= <fx at dotcloud.com>
> Date: Wed, 13 Apr 2011 10:13:39 -0700
> Subject: [PATCH 1/2] add lxc_browse function
>
> This function provide an interface to browse containers. It call a
> callback for every containers, giving the name as an argument. This
> function also return the number of containers browsed.
> ---
>  src/lxc/Makefile.am  |    3 +-
>  src/lxc/lxc.h        |   16 +++++++
>  src/lxc/lxc_browse.c |  108 
> ++++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 126 insertions(+), 1 deletions(-)
>  create mode 100644 src/lxc/lxc_browse.c
>
> diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am
> index df3d4dd..907b2c3 100644
> --- a/src/lxc/Makefile.am
> +++ b/src/lxc/Makefile.am
> @@ -50,7 +50,8 @@ liblxc_so_SOURCES = \
>      mainloop.c mainloop.h \
>      af_unix.c af_unix.h \
>      \
> -    utmp.c utmp.h
> +    utmp.c utmp.h \
> +    lxc_browse.c

Actually the lxc_* are for the cli, so I suggest the rename the file 
browse.c.

>
>  AM_CFLAGS=-I$(top_srcdir)/src
>
> diff --git a/src/lxc/lxc.h b/src/lxc/lxc.h
> index a091baa..b420010 100644
> --- a/src/lxc/lxc.h
> +++ b/src/lxc/lxc.h
> @@ -161,6 +161,22 @@ extern int lxc_checkpoint(const char *name, int 
> sfd, int flags);
>   */
>  extern int lxc_restart(const char *, int, struct lxc_conf *, int);
>
> +/**
> + * @brief Browse containers
> + *
> + * Browse all registered containers.
> + *
> + * @param [in] cb A function pointer to a callback which takes a 
> pointer to an
> + * user context and a pointer to lxcst structure. If not null, the 
> callback
> + * will be called with the ctx as well as the container name.
> + * @param [in] ctx A pointer to an user defined variable which will 
> be used as
> + * an argument to the callback. If the callback returns non zero
> + * lxcst_browse_containers stops and return with -1 with errno set to 
> EINTR.
> + *
> + * @return the number of containers on success, -1 on error with 
> errno set.
> + */
> +int lxc_browse(int (*cb)(void *ctx, const char *name), void *ctx);
> +
>  /*
>   * Returns the version number of the library
>   */
> diff --git a/src/lxc/lxc_browse.c b/src/lxc/lxc_browse.c
> new file mode 100644
> index 0000000..194ea7a
> --- /dev/null
> +++ b/src/lxc/lxc_browse.c
> @@ -0,0 +1,108 @@
> +/*
> + * lxc: linux Container library
> + *
> + * (C) Copyright IBM Corp. 2007, 2010
> + *
> + * Authors:
> + * Daniel Lezcano <dlezcano at fr.ibm.com>
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
> 02111-1307 USA
> + */
> +
> +#define _GNU_SOURCE
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <unistd.h>
> +#include <errno.h>
> +#include <dirent.h>
> +#include <string.h>
> +#include <sys/stat.h>
> +#include <err.h>
> +#undef _GNU_SOURCE
> +
> +#include "lxc.h"
> +#include "config.h"
> +
> +static int _unselect_current_and_parent(const struct dirent* d)
> +{
> +    return (strcmp(d->d_name, ".") && strcmp(d->d_name, ".."));
> +}
> +
> +static int _isdir(const char *path)
> +{
> +    struct stat sb;
> +
> +    if (stat(path, &sb) == -1) {
> +        warn("_isdir, can't stat path: %s", path);
> +        return 0;
> +    }
> +
> +    return (sb.st_mode & S_IFDIR);
> +}

These two static functions are not needed, see below.

> +
> +static char *_join_path(char *dest, size_t size,
> +        const char *left, const char *right)
> +{
> +    if (*right != '/') {
> +        if (strlen(left) + 1 + strlen(right) > size) {
> +            warn("_join_path, path overflow: %s + / + %s", left, right);
> +            return 0;
> +        }
> +        strcpy(dest, left);
> +        strcat(dest, "/");
> +        strcat(dest, right);
> +    } else {
> +        if (strlen(left) + strlen(right) > size) {
> +            warn("_join_path, path overflow: %s", right);
> +            return 0;
> +        }
> +        strcpy(dest, right);
> +    }
> +    return dest;
> +}
>
> +int lxc_browse(int (*cb)(void*, const char*), void *ctx)
> +{
> +    int             i;
> +    struct dirent   **c_vec;
> +    char            buf[PATH_MAX];
> +    int             count;
> +
> +    count = scandir(LXCPATH, &c_vec, &_unselect_current_and_parent, 
> &versionsort);
> +    if (count == -1)
> +        return (-1);
> +
> +    for (i = 0; i < count; ++i)
> +    {
> +        if (_isdir(
> +                    _join_path(buf, sizeof(buf), LXCPATH, 
> c_vec[i]->d_name))
> +                )
> +        {
> +            if (cb(ctx, c_vec[i]->d_name)) {
> +                errno = EINTR;
> +                goto abort_by_cb;
> +            }
> +        }
> +        free(c_vec[i]);
> +    }
> +    free(c_vec);
> +    return count;
> +
> +abort_by_cb:
> +    for (; i < count; ++i)
> +        free(c_vec[i]);
> +    free(c_vec);
> +    return -1;
> +}


This function could be rewritten in a simpler way. It kills the 'isdir', 
'joinpath' and '_unselect_current_and_parent'.
The errno checking with EINTR should be checked within the callback, not 
outside. This is why I removed the test.
It is preferable to let the callback to build the absolute path if it 
needs it, so only the container name is added.

By the way, this function will browse only the created container not the 
running ones. Is it what you expect François-Xavier ? Or do you need 
also the running containers ? I ask you that because you can have 
running container without being present in the LXCPATH directory.

int lxc_for_each(int (*callback)(const char *name, void *data))
{
     DIR *dir;
     struct dirent dirent, *direntp;
     int ret = 0;
     int nr = 0;

     dir = opendir(LXCPATH);
     if (!dir)
         return -1;

     while (!readdir_r(dir, &dirent, &direntp)) {

                 if (!direntp)
                         break;

                 if (direntp->d_name[0] == '.')
                         continue;

         if (direntp->d_type != DT_DIR)
             continue;

         ret = callback(direntp->d_name, data);
         if (ret < 0)
             goto out;

         nr++;
     }

     ret = nr;
out:
     closedir(dir);

     return ret;
}


> From aad1b3ccbda4c4731b2bb689f05a9607755baf11 Mon Sep 17 00:00:00 2001
> From: =?UTF-8?q?Fran=C3=A7ois-Xavier=20Bourlet?= <fx at dotcloud.com>
> Date: Wed, 13 Apr 2011 10:13:46 -0700
> Subject: [PATCH 2/2] add lxc_path()
>
> This function simply return the internal build configuration value
> LXCPATH.
> ---
>  src/lxc/conf.c |    5 +++++
>  src/lxc/conf.h |    7 +++++++
>  2 files changed, 12 insertions(+), 0 deletions(-)
>
> diff --git a/src/lxc/conf.c b/src/lxc/conf.c
> index ae5b259..9a3d8d2 100644
> --- a/src/lxc/conf.c
> +++ b/src/lxc/conf.c
> @@ -1748,3 +1748,8 @@ int lxc_setup(const char *name, struct lxc_conf 
> *lxc_conf)
>
>      return 0;
>  }
> +
> +const char* lxc_path()
> +{
> +    return LXCPATH;
> +}
> diff --git a/src/lxc/conf.h b/src/lxc/conf.h
> index 712cb3a..59






More information about the lxc-devel mailing list