Skip to content

Commit

Permalink
src/*: implement features
Browse files Browse the repository at this point in the history
Fixes: #1177
Signed-off-by: Sohan Kunkerkar <sohank2602@gmail.com>
  • Loading branch information
sohankunkerkar committed Jun 22, 2023
1 parent 7da99fb commit 62e582c
Show file tree
Hide file tree
Showing 8 changed files with 518 additions and 2 deletions.
4 changes: 2 additions & 2 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ dist-luarock: $(LUACRUN_ROCK)
endif

crun_CFLAGS = -I $(abs_top_builddir)/libocispec/src -I $(abs_top_srcdir)/libocispec/src -D CRUN_LIBDIR="\"$(CRUN_LIBDIR)\""
crun_SOURCES = src/crun.c src/run.c src/delete.c src/kill.c src/pause.c src/unpause.c src/spec.c \
crun_SOURCES = src/crun.c src/run.c src/delete.c src/kill.c src/pause.c src/unpause.c src/features.c src/spec.c \
src/exec.c src/list.c src/create.c src/start.c src/state.c src/update.c src/ps.c \
src/checkpoint.c src/restore.c src/libcrun/cloned_binary.c

Expand All @@ -143,7 +143,7 @@ endif

EXTRA_DIST = COPYING COPYING.libcrun README.md NEWS SECURITY.md rpm/crun.spec.in autogen.sh \
src/crun.h src/list.h src/run.h src/delete.h src/kill.h src/pause.h src/unpause.h \
src/create.h src/start.h src/state.h src/exec.h src/spec.h src/update.h src/ps.h \
src/create.h src/start.h src/state.h src/exec.h src/features.h src/spec.h src/update.h src/ps.h \
src/checkpoint.h src/restore.h src/libcrun/seccomp_notify.h src/libcrun/seccomp_notify_plugin.h \
src/libcrun/container.h src/libcrun/seccomp.h src/libcrun/ebpf.h \
src/libcrun/cgroup.h src/libcrun/cgroup-cgroupfs.h \
Expand Down
4 changes: 4 additions & 0 deletions src/crun.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include "spec.h"
#include "pause.h"
#include "unpause.h"
#include "features.h"
#include "ps.h"
#include "checkpoint.h"
#include "restore.h"
Expand Down Expand Up @@ -137,6 +138,7 @@ enum
COMMAND_UPDATE,
COMMAND_PAUSE,
COMMAND_UNPAUSE,
COMMAND_FEATURES,
COMMAND_PS,
COMMAND_CHECKPOINT,
COMMAND_RESTORE,
Expand All @@ -155,6 +157,7 @@ struct commands_s commands[] = { { COMMAND_CREATE, "create", crun_command_create
{ COMMAND_UPDATE, "update", crun_command_update },
{ COMMAND_PAUSE, "pause", crun_command_pause },
{ COMMAND_UNPAUSE, "resume", crun_command_unpause },
{ COMMAND_FEATURES, "features", crun_command_features },
#if HAVE_CRIU && HAVE_DLOPEN
{ COMMAND_CHECKPOINT, "checkpoint", crun_command_checkpoint },
{ COMMAND_RESTORE, "restore", crun_command_restore },
Expand All @@ -170,6 +173,7 @@ static char doc[] = "\nCOMMANDS:\n"
"\tcreate - create a container\n"
"\tdelete - remove definition for a container\n"
"\texec - exec a command in a running container\n"
"\tfeatures - show the enabled features\n"
"\tlist - list known containers\n"
"\tkill - send a signal to the container init process\n"
"\tps - show the processes in the container\n"
Expand Down
287 changes: 287 additions & 0 deletions src/features.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,287 @@
/*
* crun - OCI runtime written in C
*
* crun is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* crun 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with crun. If not, see <http://www.gnu.org/licenses/>.
*/

#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <argp.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>

#include <yajl/yajl_tree.h>
#include <yajl/yajl_gen.h>

#include "crun.h"
#include "libcrun/container.h"
#include "libcrun/utils.h"

#define cleanup_struct_features __attribute__ ((cleanup (cleanup_struct_features_free)))

static char doc[] = "OCI runtime";

static struct argp_option options[] = { { 0 } };

static char args_doc[] = "features";

const unsigned char *json_string;

size_t json_length;

static error_t
parse_opt (int key, char *arg arg_unused, struct argp_state *state arg_unused)
{
if (key != ARGP_KEY_NO_ARGS)
{
return ARGP_ERR_UNKNOWN;
}

return 0;
}

static struct argp run_argp = { options, parse_opt, args_doc, doc, NULL, NULL, NULL };

void
add_string_to_json (yajl_gen json_gen, const char *key, const char *value)
{
yajl_gen_string (json_gen, (const unsigned char *) key, strlen (key));
yajl_gen_string (json_gen, (const unsigned char *) value, strlen (value));
}

void
add_bool_to_json (yajl_gen json_gen, const char *key, int value)
{
yajl_gen_string (json_gen, (const unsigned char *) key, strlen (key));
yajl_gen_bool (json_gen, value);
}

void
add_array_to_json (yajl_gen json_gen, const char *key, const char **array)
{
yajl_gen_string (json_gen, (const unsigned char *) key, strlen (key));
yajl_gen_array_open (json_gen);

for (size_t i = 0; array[i] != NULL; i++)
{
yajl_gen_string (json_gen, (const unsigned char *) array[i], strlen (array[i]));
}

yajl_gen_array_close (json_gen);
}

void
crun_features_add_hooks (yajl_gen json_gen, const char **hooks)
{
add_array_to_json (json_gen, "hooks", hooks);
}

void
crun_features_add_mount_options (yajl_gen json_gen, const char **mount_options)
{
add_array_to_json (json_gen, "mountOptions", mount_options);
}

void
crun_features_add_namespaces (yajl_gen json_gen, const struct linux_info_s *linux)
{
add_array_to_json (json_gen, "namespaces", linux->namespaces);
}

void
crun_features_add_capabilities (yajl_gen json_gen, const struct linux_info_s *linux)
{
add_array_to_json (json_gen, "capabilities", linux->capabilities);
}

void
crun_features_add_cgroup_info (yajl_gen json_gen, const struct linux_info_s *linux)
{
yajl_gen_string (json_gen, (const unsigned char *) "cgroup", strlen ("cgroup"));
yajl_gen_map_open (json_gen);

add_bool_to_json (json_gen, "v1", linux->cgroup.v1);
add_bool_to_json (json_gen, "v2", linux->cgroup.v2);
add_bool_to_json (json_gen, "systemd", linux->cgroup.systemd);
add_bool_to_json (json_gen, "systemdUser", linux->cgroup.systemdUser);

yajl_gen_map_close (json_gen);
}

void
crun_features_add_seccomp_info (yajl_gen json_gen, const struct linux_info_s *linux)
{
yajl_gen_string (json_gen, (const unsigned char *) "seccomp", strlen ("seccomp"));
yajl_gen_map_open (json_gen);

yajl_gen_string (json_gen, (const unsigned char *) "/* TODO: */", strlen ("/* TODO: */"));

yajl_gen_map_close (json_gen);
}

void
crun_features_add_apparmor_info (yajl_gen json_gen, const struct linux_info_s *linux)
{
yajl_gen_string (json_gen, (const unsigned char *) "apparmor", strlen ("apparmor"));
yajl_gen_map_open (json_gen);

add_bool_to_json (json_gen, "enabled", linux->apparmor.enabled);

// Close the map for apparmor
yajl_gen_map_close (json_gen);
}

void
crun_features_add_selinux_info (yajl_gen json_gen, const struct linux_info_s *linux)
{
yajl_gen_string (json_gen, (const unsigned char *) "selinux", strlen ("selinux"));
yajl_gen_map_open (json_gen);

add_bool_to_json (json_gen, "enabled", linux->selinux.enabled);

// Close the map for selinux
yajl_gen_map_close (json_gen);
}

void
crun_features_add_linux_info (yajl_gen json_gen, const struct linux_info_s *linux)
{
yajl_gen_string (json_gen, (const unsigned char *) "linux", strlen ("linux"));
yajl_gen_map_open (json_gen);

crun_features_add_namespaces (json_gen, linux);
crun_features_add_capabilities (json_gen, linux);
crun_features_add_cgroup_info (json_gen, linux);
crun_features_add_seccomp_info (json_gen, linux);
crun_features_add_apparmor_info (json_gen, linux);
crun_features_add_selinux_info (json_gen, linux);

yajl_gen_map_close (json_gen);
}

static inline void
cleanup_struct_features_free (struct features_info_s **info)
{
if (info == NULL || *info == NULL)
return;

struct features_info_s *ptr = *info;

// Free oci_version_min if it is not NULL
if (ptr->oci_version_min != NULL)
{
free ((void *) ptr->oci_version_min);
ptr->oci_version_min = NULL; // Set to NULL after freeing
}

// Free oci_version_max if it is not NULL
if (ptr->oci_version_max != NULL)
{
free ((void *) ptr->oci_version_max);
ptr->oci_version_max = NULL; // Set to NULL after freeing
}
if (ptr->hooks != NULL)
{
for (size_t i = 0; ptr->hooks[i] != NULL; i++)
{
free ((void *) ptr->hooks[i]);
}
free (ptr->hooks);
}
if (ptr->mount_options != NULL)
{
for (size_t i = 0; ptr->mount_options[i] != NULL; i++)
{
free ((void *) ptr->mount_options[i]);
}
free (ptr->mount_options);
}
if (ptr->linux.namespaces != NULL)
{
for (size_t i = 0; ptr->linux.namespaces[i] != NULL; i++)
{
free ((void *) ptr->linux.namespaces[i]);
}
free (ptr->linux.namespaces);
}

if (ptr->linux.capabilities != NULL)
{
for (size_t i = 0; ptr->linux.capabilities[i] != NULL; i++)
{
free ((void *) ptr->linux.capabilities[i]);
}
free (ptr->linux.capabilities);
}

free (ptr);
*info = NULL;
}

int
crun_command_features (struct crun_global_arguments *global_args, int argc, char **argv, libcrun_error_t *err)
{
argp_parse (&run_argp, argc, argv, 0, 0, &options);

// Call the function in features.c to gather the feature information
cleanup_struct_features struct features_info_s *info = NULL;
int result = libcrun_container_get_features (&info);
if (result != 0)
{
libcrun_make_error (err, 0, "Failed to gather features information.");
return result;
}

// Prepare the JSON output
yajl_gen json_gen = yajl_gen_alloc (NULL);
if (json_gen == NULL)
{
libcrun_make_error (err, errno, "Failed to initialize json structure.");
return 0;
}
yajl_gen_status status;

yajl_gen_config (json_gen, yajl_gen_beautify, 1); // Optional: Enable pretty formatting

// Start building the JSON
yajl_gen_map_open (json_gen);

// Add ociVersionMin field
add_string_to_json (json_gen, "ociVersionMin", info->oci_version_min);

// Add ociVersionMax field
add_string_to_json (json_gen, "ociVersionMax", info->oci_version_max);

// Add hooks array
crun_features_add_hooks (json_gen, info->hooks);

// Add mountOptions array
crun_features_add_mount_options (json_gen, info->mount_options);

// Add linux struct info
crun_features_add_linux_info (json_gen, &info->linux);

// End building the JSON
yajl_gen_map_close (json_gen);

yajl_gen_get_buf (json_gen, &json_string, &json_length);

printf ("%s", (const char *) json_string);

yajl_gen_free (json_gen);

return 0;
}
25 changes: 25 additions & 0 deletions src/features.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* crun - OCI runtime written in C
*
* Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano <giuseppe@scrivano.org>
* crun is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* crun 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with crun. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef FEATURES_H
#define FEATURES_H

#include "crun.h"

int crun_command_features (struct crun_global_arguments *global_args, int argc, char **argv, libcrun_error_t *error);

#endif
Loading

0 comments on commit 62e582c

Please sign in to comment.