Skip to content
This repository has been archived by the owner on Oct 2, 2024. It is now read-only.

Commit

Permalink
map json file specs to Charliecloud arguments - issue
Browse files Browse the repository at this point in the history
  • Loading branch information
kchilleri committed Jun 4, 2024
1 parent beb4ee8 commit 178208a
Show file tree
Hide file tree
Showing 3 changed files with 181 additions and 159 deletions.
178 changes: 176 additions & 2 deletions bin/ch-run.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
#include "ch_core.h"
#include "ch_misc.h"

#include "cJSON.h"

/** Constants and macros **/

/* Environment variables used by --join parameters. */
Expand Down Expand Up @@ -62,6 +64,7 @@ const struct argp_option options[] = {
{ "test", -17, "TEST", 0, "do test TEST" },
{ "mount", 'm', "DIR", 0, "SquashFS mount point"},
{ "no-passwd", -9, 0, 0, "don't bind-mount /etc/{passwd,group}"},
{ "oci", 'o', 0, 0, "run as an oci bundle" },
{ "private-tmp", 't', 0, 0, "use container-private /tmp" },
{ "quiet", 'q', 0, 0, "print less output (can be repeated)"},
#ifdef HAVE_SECCOMP
Expand Down Expand Up @@ -114,6 +117,38 @@ void privs_verify_invoking();
char *storage_default(void);
extern void warnings_reprint(void);

struct json_dispatch {
char *name;
struct json_dispatch *children;
void (*f)(cJSON *, struct args *args);
};

void readJSONFile(const char *filename, struct args *args);
void visit(struct json_dispatch actions[], cJSON *json, struct args *args);
void dispatch(struct json_dispatch action, cJSON *json, struct args *args);
void oci_ociVersion(cJSON *json, struct args *args);
void oci_env(cJSON *json, struct args *args);
void oci_cwd(cJSON *json, struct args *args);
void oci_path(cJSON *json, struct args *args);
void oci_readonly(cJSON *json, struct args *args);

struct json_dispatch oci_process[] = {
{ "env", NULL, oci_env },
{ "cwd", NULL, oci_cwd },
{ }
};
struct json_dispatch oci_root[] = {
{ "path", NULL, oci_path },
{ "readonly", NULL, oci_readonly },
{ }
};
struct json_dispatch oci_top[] = {
{ "ociVersion", NULL, oci_ociVersion },
{ "process", oci_process },
{ "root", oci_root },
{ }
};


/** Global variables **/

Expand Down Expand Up @@ -193,7 +228,10 @@ int main(int argc, char *argv[])
args.c.img_ref = argv[arg_next++];
args.c.newroot = realpath_(args.c.newroot, true);
args.storage_dir = realpath_(args.storage_dir, true);
args.c.type = image_type(args.c.img_ref, args.storage_dir);

if (args.c.type != IMG_OCI_BUNDLE) {
args.c.type = image_type(args.c.img_ref, args.storage_dir);
}

switch (args.c.type) {
case IMG_DIRECTORY:
Expand All @@ -209,7 +247,15 @@ int main(int argc, char *argv[])
break;
case IMG_OCI_BUNDLE:
/* Parse config.json file -> containerize */
args.c.newroot = path_join(args.c.img_ref, "/rootfs");
char *rootfs = path_join(args.c.img_ref, "rootfs");
char *conff = path_join(args.c.img_ref, "config.json");

Tf (path_exists(rootfs, NULL, true), "%s: No such file or directory", rootfs);
Tf (path_exists(conff, NULL, true), "%s: No such file or directory", conff);
//printf("initial dir before: %s\n", args.initial_dir);
readJSONFile(conff, &args);
//args.c.newroot = rootfs;
printf("args.initial_dir is: %s\n", args.initial_dir);
break;
case IMG_SQUASH:
#ifndef HAVE_LIBSQUASHFUSE
Expand Down Expand Up @@ -531,6 +577,7 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state)
}
break;
case 'c': // --cd
printf("key is: %d\n", key);
args->initial_dir = arg;
break;
case 'g': // --gid
Expand All @@ -545,6 +592,9 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state)
Ze ((arg[0] == '\0'), "mount point can't be empty string");
args->c.newroot = arg;
break;
case 'o': // --oci
args->c.type = IMG_OCI_BUNDLE;
break;
case 's': // --storage
args->storage_dir = arg;
if (!path_exists(arg, NULL, false))
Expand Down Expand Up @@ -649,3 +699,127 @@ char *storage_default(void)

return storage;
}

void readJSONFile(const char *filename, struct args *args) {

FILE *file = fopen(filename, "rb");
char *buffer = NULL;
size_t length;
size_t file_len;

if (file == NULL) {
fprintf(stderr, "Error: could not open file %s\n", filename);
return;
}

// Get the file length
fseek(file, 0, SEEK_END);
length = ftell(file);
fseek(file, 0, SEEK_SET);
// Allocate content buffer
buffer = malloc(length);
file_len = fread(buffer, 1, length, file);
printf("Read %lu bytes of %lu\n", file_len, length);

fclose(file);

// Parse the JSON data
cJSON *json = cJSON_Parse(buffer);
// Check if parsing was successful
if (json == NULL) {
const char *error_ptr = cJSON_GetErrorPtr();
if (error_ptr != NULL) {
fprintf(stderr, "Error before: %s\n", error_ptr);
}
goto end;
}

// Print the JSON data
char *json_tree = cJSON_Print(json);
if (json_tree == NULL)
{
fprintf(stderr, "Failed to print JSON tree.\n");
}
//printf("%s\n", json_tree);

// Process the JSON data
visit(oci_top, json, args);

// Clean up
end:
cJSON_Delete(json);
free(buffer);
}

void dispatch(struct json_dispatch action, cJSON *json, struct args *args) {
if (action.f != NULL)
action.f(json, args);
if (action.children != NULL)
visit(action.children, json, args);
}


void visit(struct json_dispatch actions[], cJSON *json, struct args *args) {
for (int i =0; actions[i].name != NULL; i++) {
cJSON *subtree = cJSON_GetObjectItem(json, actions[i].name);
if (cJSON_IsArray(subtree)) {
cJSON *elem;
cJSON_ArrayForEach(elem, subtree)
dispatch(actions[i], elem, args);
} else {
dispatch(actions[i], subtree, args);
}
}
}

void oci_ociVersion(cJSON *json, struct args *args) {
// Need to validate this version. Not sure how just yet.
printf("oci_ociVersion: %s\n", json->valuestring);
}


void oci_env(cJSON *json, struct args *args) {
// TO DO: corresponds to --set-env
printf("oci_env: %s\n", json->valuestring);
}


void oci_cwd(cJSON *json, struct args *args) {
// corresponds to --cd
//printf("oci_cwd: %s\n", json->valuestring);
if (args->initial_dir == NULL) {
args->initial_dir = json->valuestring;
}
//printf("after assignment in oci_cwd: %c\n",json->valuestring);
printf("oci_cwd is: %s\n", args->initial_dir);
}


void oci_path(cJSON *json, struct args *args) {
//printf("oci_path: %s\n", json->valuestring);

args->c.newroot = json->valuestring;

if (!path_exists(args->c.newroot, NULL, true)) {
args->c.newroot = path_join(args->c.img_ref, json->valuestring);
}

//printf("args.c.newroot in oci_path function is: %s\n", args->c.newroot);
}


void oci_readonly(cJSON *json, struct args *args) {
/*const char *bool_to_str;
if (cJSON_IsTrue(json)) {
bool_to_str = "true";
} if (cJSON_IsFalse(json)) {
bool_to_str = "false";
}*/

//printf("oci_readonly: %s\n", bool_to_str);

if (cJSON_IsFalse(json)) {
args->c.writable = true;
}
}
9 changes: 5 additions & 4 deletions bin/ch_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -391,8 +391,8 @@ enum img_type image_type(const char *ref, const char *storage_dir)
struct stat st;
FILE *fp;
char magic[4]; // four bytes, not a string
char *conff = path_join(ref, "/config.json");
char *rootfs = path_join(ref, "/rootfs");
//char *conff = path_join(ref, "/config.json");
//char *rootfs = path_join(ref, "/rootfs");

// If there’s a directory in storage where we would expect there to be if
// ref were an image name, assume it really is an image name.
Expand All @@ -406,11 +406,12 @@ enum img_type image_type(const char *ref, const char *storage_dir)
// If ref is the path to a directory that contains rootfs directory
// and config.json file, assume it is an oci bundle
if (S_ISDIR(st.st_mode)) {
if (path_exists(rootfs, NULL, true) && path_exists(conff, NULL, true)) {
/*if (path_exists(rootfs, NULL, true) && path_exists(conff, NULL, true)) {
return IMG_OCI_BUNDLE;
} else {
return IMG_DIRECTORY;
}
}*/
return IMG_DIRECTORY;
}

// Now we know it’s file-like enough to read. See if it has the SquashFS
Expand Down
Loading

0 comments on commit 178208a

Please sign in to comment.