view container.c @ 8:fe254ba0818d

Add missing frees
author Louis Opter <louis@dotcloud.com>
date Sun, 02 Jan 2011 01:14:56 +0100
parents 8339ab15527d
children
line wrap: on
line source

#include <sys/types.h>
#include <sys/stat.h>

#include <assert.h>
#include <dirent.h>
#include <err.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>

#include "lxcstats.h"
#include "_lxcstats.h"

static int
_lxcst_unselect_current_and_parent(const struct dirent* d)
{
    return (strcmp(d->d_name, ".") && strcmp(d->d_name, ".."));
}

struct lxcst *
_lxcst_container_new(const struct _lxcst_controller *ct, const char *name)
{
    char            buf[256];
    struct lxcst    *c;

    assert(ct);
    assert(name);

    c = calloc(1, sizeof(*c));
    if (!c)
        return (NULL);

    _lxcst_join_path(buf, sizeof(buf), ct->cgroup_dir, name);

    c->name = strdup(name);
    c->cgroup_dir = strdup(buf);
    if (!c->name || !c->cgroup_dir)
        goto free_container;

    return (c);

free_container:
    free(c->name);
    free(c->cgroup_dir);
    free(c);
    return (NULL);
}

void
_lxcst_container_delete(struct lxcst *c)
{
    if (c) {
        free(c->name);
        free(c->cgroup_dir);
        free(c->cpuacct.percpu);
        free(c);
    }
}

/*
 * Should be equivalent to the number of directories found under /var/lib/lxc/
 */
int
_lxcst_container_count(const struct _lxcst_controller *ct)
{
    int             n;
    struct dirent   **c_vec;
    int             count;
    char            buf[PATH_MAX];

    n = scandir(ct->lxc_dir, &c_vec, &_lxcst_unselect_current_and_parent, NULL);
    if (n != -1) {
        count = n;
        while (n--) {
            if (!_lxcst_isdir(_lxcst_join_path(buf, sizeof(buf), ct->lxc_dir, c_vec[n]->d_name)))
                --count;
            free(c_vec[n]);
        }
        free(c_vec);
        return (count);
    }

    return (-1);
}

int
_lxcst_container_read_infos(struct lxcst *c)
{
    int i;

    assert(c);

    for (i = 0; _lxcst_probes[i].fn; ++i)
        if (_lxcst_probes[i].fn((c)))
            warn("%s probe failed for container %s", _lxcst_probes[i].name, c->name);

    return (0);
}

int
lxcst_span_containers(lxcst_handle *hdl, int (*cb)(void *, const struct lxcst *), void *ctx)
{
    int             n;
    struct dirent   **c_vec;
    struct lxcst    *c;
    char            buf[PATH_MAX];

    assert(hdl);
    assert(hdl->cgroup_dir);
    assert(cb);

    _lxcst_globals_reset();

    n = scandir(hdl->cgroup_dir, &c_vec, &_lxcst_unselect_current_and_parent, NULL);
    if (n > 0) {
        while (n--) {
            if (_lxcst_isdir(_lxcst_join_path(buf, sizeof(buf), hdl->cgroup_dir, c_vec[n]->d_name))) {
                c = _lxcst_container_new(hdl, c_vec[n]->d_name);
                _lxcst_globals.running_containers++;
                if (c && _lxcst_container_read_infos(c) == 0
                    && cb(ctx, c)) {
                    errno = EINTR;
                    goto abort_by_cb;
                }
                _lxcst_container_delete(c);
            }
            free(c_vec[n]);
        }
        free(c_vec);
    } else if (n < 0) {
        return (-1);
    }

    n = _lxcst_container_count(hdl);
    if (n == -1) {
        warn("can't get the total number of containers");
        return (-1);
    }

    _lxcst_globals.stopped_containers = n - _lxcst_globals.running_containers;

    return (0);

abort_by_cb:
    _lxcst_container_delete(c);
    free(c_vec[n + 1]);
    while (n--)
        free(c_vec[n]);
    free(c_vec);
    return (-1);
}