summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/tools/Makefile.am4
-rw-r--r--src/tools/lscgroup.c295
2 files changed, 298 insertions, 1 deletions
diff --git a/src/tools/Makefile.am b/src/tools/Makefile.am
index e2338bd..d541445 100644
--- a/src/tools/Makefile.am
+++ b/src/tools/Makefile.am
@@ -3,7 +3,7 @@ LDADD = $(top_srcdir)/src/.libs/libcgroup.la
if WITH_TOOLS
-bin_PROGRAMS = cgexec cgclassify cgcreate cgset cgdelete lssubsys
+bin_PROGRAMS = cgexec cgclassify cgcreate cgset cgdelete lssubsys lscgroup
sbin_PROGRAMS = cgconfigparser cgclear
@@ -23,6 +23,8 @@ cgdelete_SOURCES = cgdelete.c tools-common.c tools-common.h
lssubsys_SOURCES = lssubsys.c
+lscgroup_SOURCES = tools-common.c lscgroup.c
+
install-exec-hook:
chmod u+s $(DESTDIR)$(bindir)/cgexec
diff --git a/src/tools/lscgroup.c b/src/tools/lscgroup.c
new file mode 100644
index 0000000..5e3e80b
--- /dev/null
+++ b/src/tools/lscgroup.c
@@ -0,0 +1,295 @@
+/* Copyright (C) 2009 Red Hat, Inc. All Rights Reserved.
+ * Written by Ivana Hutarova Varekova <varekova@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2.1 of the GNU Lesser General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+
+#include <libcgroup.h>
+#include <libcgroup-internal.h>
+#include "tools-common.h"
+
+enum flag{
+ /*
+ * the flag set if there is a cgroup on output
+ * if there is no one we want to display all cgroups
+ */
+ FL_LIST = 1
+};
+
+void usage(int status, char *program_name)
+{
+ if (status != 0) {
+ fprintf(stderr, "Wrong input parameters,"
+ " try %s -h' for more information.\n",
+ program_name);
+ } else {
+ fprintf(stdout, "Usage: %s [<controllers>:<path>] [...]\n",
+ program_name);
+ fprintf(stdout, "list all cgroups\n");
+ }
+}
+
+/*
+ * if the info about controller "name" should be printed,
+ * then the function returns nonzero value
+ */
+int is_ctlr_on_list(struct cgroup_group_spec *cgroup_list,
+ char name[FILENAME_MAX])
+{
+ int j;
+
+ for (j = 0; cgroup_list->controllers[j] != NULL; j++)
+ if (strcmp(cgroup_list->controllers[j], name) == 0)
+ return 1;
+
+ return 0;
+}
+
+void print_info(struct cgroup_file_info *info, char *name, int pref)
+{
+ if (info->type == CGROUP_FILE_TYPE_DIR) {
+ if (info->full_path[pref] == '/')
+ printf("%s:%s\n", name, &info->full_path[pref]);
+ else
+ printf("%s:/%s\n", name, &info->full_path[pref]);
+ }
+}
+
+/* display controller:/input_path cgroups */
+int display_controller_data(char *input_path, char *controller, char *name)
+{
+ int ret;
+ void *handle;
+ struct cgroup_file_info info;
+ char cgroup_dir_path[FILENAME_MAX];
+ char input_dir_path[FILENAME_MAX];
+ char *end;
+ int lvl;
+ int len;
+
+ ret = cgroup_walk_tree_begin(controller, input_path, 0,
+ &handle, &info, &lvl);
+ if (ret != 0)
+ return ret;
+
+ strncpy(cgroup_dir_path, info.full_path, FILENAME_MAX);
+ /* remove problematic '/' characters from cgroup directory path*/
+ len = strlen(cgroup_dir_path)-1;
+ while (cgroup_dir_path[len] == '/')
+ len--;
+
+ cgroup_dir_path[len+1] = '\0';
+
+ strncpy(input_dir_path, input_path, FILENAME_MAX);
+ /* remove problematic '/' characters from input path*/
+ len = strlen(input_dir_path)-1;
+ while (input_dir_path[len] == '/')
+ len--;
+
+ input_dir_path[len+1] = '\0';
+
+ len = strlen(cgroup_dir_path) - strlen(input_dir_path);
+
+ print_info(&info, name, len);
+ while ((ret = cgroup_walk_tree_next(0, &handle, &info, lvl)) == 0)
+ print_info(&info, name, len);
+
+ cgroup_walk_tree_end(&handle);
+ if (ret == ECGEOF)
+ ret = 0;
+
+ return ret;
+}
+
+/*
+ * print data about input cgroup_list cgroups
+ * if FL_LIST flag is set then if the function does not find
+ * the cgroup it returns ECGEOF
+ */
+
+int print_cgroup(struct cgroup_group_spec *cgroup_spec, int flags)
+{
+ int ret = 0;
+ void *handle;
+ struct cgroup_mount_point controller;
+ char path[FILENAME_MAX];
+ char con_name[FILENAME_MAX];
+ char all_conts[FILENAME_MAX];
+ int output = 0;
+
+ path[0] = '\0';
+ con_name[0] = '\0';
+ all_conts[0] = '\0';
+
+ ret = cgroup_get_controller_begin(&handle, &controller);
+
+ /* go through the list of controllers/mount point pairs */
+ while (ret == 0) {
+ if (strcmp(path, controller.path) == 0) {
+ /* if it is still the same mount point */
+ strncat(all_conts, ",",
+ FILENAME_MAX-strlen(all_conts)-1);
+ strncat(all_conts, controller.name,
+ FILENAME_MAX-strlen(all_conts)-1);
+ } else {
+ /* we got new mount point, print it if needed */
+ if (output) {
+ ret = display_controller_data(
+ cgroup_spec->path,
+ con_name, all_conts);
+ if (ret)
+ return ret;
+ if ((flags & FL_LIST) != 0) {
+ /* we succesfully finish printing */
+ output = 0;
+ break;
+ }
+ }
+
+ output = 0;
+ strncpy(all_conts, controller.name, FILENAME_MAX);
+ all_conts[FILENAME_MAX-1] = '\0';
+ strncpy(con_name, controller.name, FILENAME_MAX);
+ con_name[FILENAME_MAX-1] = '\0';
+ strncpy(path, controller.path, FILENAME_MAX);
+ path[FILENAME_MAX-1] = '\0';
+ }
+
+ /* set output flag */
+ if ((output == 0) && (!(flags & FL_LIST) ||
+ (is_ctlr_on_list(cgroup_spec, controller.name))))
+ output = 1;
+
+ /* the actual controller should not be printed */
+ ret = cgroup_get_controller_next(&handle, &controller);
+ }
+
+ cgroup_get_controller_end(&handle);
+ if (ret != ECGEOF)
+ return ret;
+
+ if (output) {
+ ret = display_controller_data(
+ cgroup_spec->path,
+ con_name, all_conts);
+ }
+
+ return ret;
+}
+
+
+int cgroup_list_cgroups(char *tname,
+ struct cgroup_group_spec *cgroup_list[],
+ int flags)
+{
+ int ret = 0;
+ int final_ret = 0;
+ int i = 0;
+
+ /* initialize libcgroup */
+ ret = cgroup_init();
+ if (ret) {
+ fprintf(stderr, "cgroups can't be listed: %s\n",
+ cgroup_strerror(ret));
+ return ret;
+ }
+
+ if ((flags & FL_LIST) == 0) {
+ struct cgroup_group_spec *cgroup_spec;
+ cgroup_spec = calloc(1, sizeof(struct cgroup_group_spec));
+ /* we have to print all cgroups */
+ ret = print_cgroup(cgroup_spec, flags);
+ free(cgroup_spec);
+ if (ret == 0) {
+ final_ret = 0;
+ } else {
+ final_ret = ret;
+ fprintf(stderr, "cgroups can't be listed: %s\n",
+ cgroup_strerror(ret));
+ }
+ } else {
+ /* we have he list of controllers which should be print */
+ while ((cgroup_list[i] != NULL)
+ && ((ret == ECGEOF) || (ret == 0))) {
+ ret = print_cgroup(cgroup_list[i], flags);
+ if (ret != 0) {
+ if (ret == ECGEOF) {
+ /* controller was not found */
+ final_ret = ECGFAIL;
+ } else {
+ /* other problem */
+ final_ret = ret;
+ }
+ fprintf(stderr,
+ "%s: cannot find group %s..:%s: %s\n",
+ tname, cgroup_list[i]->controllers[0],
+ cgroup_list[i]->path,
+ cgroup_strerror(final_ret));
+ }
+ i++;
+ }
+ }
+ return final_ret;
+}
+
+int main(int argc, char *argv[])
+{
+
+ int ret = 0;
+ int c;
+
+ int flags = 0;
+
+ struct cgroup_group_spec *cgroup_list[CG_HIER_MAX];
+
+ static struct option options[] = {
+ {"help", 0, 0, 'h'},
+ {0, 0, 0, 0}
+ };
+
+ /* parse arguments */
+ while ((c = getopt_long(argc, argv, "h", options, NULL)) > 0) {
+ switch (c) {
+ case 'h':
+ usage(0, argv[0]);
+ return 0;
+ default:
+ usage(1, argv[0]);
+ return -1;
+ }
+ }
+
+ memset(cgroup_list, 0, sizeof(cgroup_list));
+
+ /* no cgroup on input */
+ if (optind < argc)
+ flags |= FL_LIST;
+
+ /* read the list of controllers */
+ while (optind < argc) {
+ if (parse_cgroup_spec(cgroup_list, argv[optind])) {
+ fprintf(stderr, "%s: cgroup controller"
+ " and path parsing failed (%s)\n",
+ argv[0], argv[optind]);
+ return -1;
+ }
+ optind++;
+ }
+
+ /* print the information, based on list of input cgroups and flags */
+ ret = cgroup_list_cgroups(argv[0], cgroup_list, flags);
+
+ return ret;
+}