summaryrefslogtreecommitdiff
path: root/src/sf.jail/state.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sf.jail/state.c')
-rw-r--r--src/sf.jail/state.c396
1 files changed, 396 insertions, 0 deletions
diff --git a/src/sf.jail/state.c b/src/sf.jail/state.c
new file mode 100644
index 0000000..893961e
--- /dev/null
+++ b/src/sf.jail/state.c
@@ -0,0 +1,396 @@
+#include "state.h"
+
+// FREE
+
+void
+Free_interface_configuration(interface_configuration *E)
+{
+ free(E->Name);
+ switch(E->Type)
+ {
+ case interface_type_eiface: break;
+ case interface_type_steal: free(E->steal.Interface); break;
+ case interface_type_COUNT:
+ default: __builtin_unreachable();
+ }
+}
+
+void
+Free_interfaces_configuration(interfaces_configuration *E)
+{
+ for(size_t i = 0; i < E->Count; ++i) Free_interface_configuration(E->_ + i);
+ free(E->_);
+}
+
+void
+Free_mapping(mapping *E)
+{
+ free(E->Source);
+ free(E->Target);
+}
+
+void
+Free_filesystem_configuration(filesystem_configuration *E)
+{
+ for(size_t i = 0; i < E->LayerCount; ++i) free(E->Layer[i]);
+ if(E->Layer != NULL) free(E->Layer);
+ if(E->Temporary != NULL) free(E->Temporary);
+ for(size_t i = 0; i < E->VolumeCount; ++i) Free_mapping(E->Volume + i);
+ if(E->Volume != NULL) free(E->Volume);
+}
+
+void
+Free_configuration(configuration *E)
+{
+ Free_filesystem_configuration(&E->Filesystem);
+ Free_interfaces_configuration(&E->Interfaces);
+ Free_string_array(&E->Init);
+ Free_string_array(&E->Shutdown);
+}
+
+void
+Free_interface(interface *E)
+{
+ UNUSED(E);
+}
+
+void
+Free_interfaces(interfaces *E)
+{
+ for(size_t i = 0; i < E->Count; ++i) Free_interface(E->_ + i);
+ free(E->_);
+}
+
+void
+Free_data(data *E)
+{
+ Free_interfaces(&E->Interfaces);
+}
+
+// PARSE
+
+char *
+Parse_interface_type(interface_type *E, ucl_object_t const *root, char const *Position)
+{
+ char *Error;
+ UCL_CHECK_ROOT(STRING);
+ char const *Type = ucl_object_tostring(root);
+ for(interface_type i = 0; i < interface_type_COUNT; ++i)
+ {
+ if(strcmp(interface_type_Names[i], Type) == 0)
+ {
+ *E = i;
+ return NULL;
+ }
+ }
+ asprintf(&Error, "%s invalid interface type '%s'", Position, Type);
+ goto error;
+error:
+ return Error;
+}
+
+char *
+Parse_interface_configuration(interface_configuration *E, ucl_object_t const *root, char const *Position)
+{
+ char *Error;
+ UCL_CHECK_ROOT(OBJECT);
+ {
+ char *NewPosition;
+ asprintf(&NewPosition, "%s.type", Position);
+ Error = Parse_interface_type(&E->Type, ucl_object_lookup(root, "type"), NewPosition);
+ free(NewPosition);
+ if(Error != NULL) goto error;
+ }
+ switch(E->Type)
+ {
+ case interface_type_eiface: break;
+ case interface_type_steal:
+ {
+ ucl_object_t const *interface = ucl_object_lookup(root, "interface");
+ UCL_CHECK(interface, STRING);
+ E->steal.Interface = strdup(ucl_object_tostring(interface));
+ break;
+ }
+ case interface_type_COUNT:
+ default: __builtin_unreachable();
+ }
+ return NULL;
+error:
+ return Error;
+}
+
+char *
+Parse_interfaces_configuration(interfaces_configuration *E, ucl_object_t const *root, char const *Position)
+{
+ char *Error;
+ UCL_CHECK_ROOT(OBJECT);
+ E->Count = root->len;
+ E->_ = calloc(sizeof(interface_configuration), E->Count);
+ {
+ ucl_object_iter_t it = NULL;
+ for(E->Count = 0; E->Count < root->len; ++E->Count)
+ {
+ ucl_object_t const *v = ucl_iterate_object(root, &it, true);
+ if(v == NULL) break;
+ char const *k = ucl_object_key(v);
+ if(k == NULL) continue;
+ interface_configuration *I = E->_ + E->Count;
+ char *NewPosition;
+ asprintf(&NewPosition, "%s['%s']", Position, k);
+ Error = Parse_interface_configuration(I, v, NewPosition);
+ free(NewPosition);
+ if(Error != NULL) goto error;
+ I->Name = strdup(k);
+ }
+ }
+ return NULL;
+error:
+ Free_interfaces_configuration(E);
+ return Error;
+}
+
+char *
+Parse_mapping(mapping *E, ucl_object_t const *root, char const *Position)
+{
+ char *Error;
+ UCL_CHECK_ROOT(OBJECT);
+ ucl_object_t const *source = ucl_object_lookup(root, "source");
+ UCL_CHECK(source, STRING);
+ ucl_object_t const *target = ucl_object_lookup(root, "target");
+ UCL_CHECK(target, STRING);
+ E->Source = strdup(ucl_object_tostring(source));
+ E->Target = strdup(ucl_object_tostring(target));
+ return NULL;
+error:
+ return Error;
+}
+
+char *
+Parse_filesystem_configuration(filesystem_configuration *E, ucl_object_t const *root, char const *Position)
+{
+ char *Error;
+ UCL_CHECK_ROOT(OBJECT);
+ ucl_object_t const *layers = ucl_object_lookup(root, "layers");
+ UCL_CHECK_OPTIONAL(layers, ARRAY);
+ ucl_object_t const *temporary = ucl_object_lookup(root, "temporary");
+ UCL_CHECK_OPTIONAL(temporary, STRING);
+ ucl_object_t const *volumes = ucl_object_lookup(root, "volumes");
+ UCL_CHECK_OPTIONAL(volumes, ARRAY);
+ ucl_object_t const *devfs = ucl_object_lookup(root, "devfs");
+ UCL_CHECK_OPTIONAL(devfs, INT);
+ if(layers != NULL)
+ {
+ E->Layer = calloc(sizeof(char *), layers->len);
+ ucl_object_iter_t it = NULL;
+ for(E->LayerCount = 0; E->LayerCount < layers->len; ++E->LayerCount)
+ {
+ ucl_object_t const *v = ucl_iterate_object(layers, &it, true);
+ if(v == NULL) break;
+ char const *k = ucl_object_key(v);
+ if(k != NULL) continue;
+ if(v->type != UCL_STRING)
+ {
+ asprintf(&Error, "%s.layers[%zu] is not " UCL_CHECK_HELPER(STRING), Position, E->LayerCount);
+ goto error;
+ }
+ E->Layer[E->LayerCount] = strdup(ucl_object_tostring(v));
+ }
+ }
+ if(temporary != NULL) E->Temporary = strdup(ucl_object_tostring(temporary));
+ if(volumes != NULL)
+ {
+ E->Volume = calloc(sizeof(mapping), volumes->len);
+ ucl_object_iter_t it = NULL;
+ for(E->VolumeCount = 0; E->VolumeCount < volumes->len; ++E->VolumeCount)
+ {
+ ucl_object_t const *v = ucl_iterate_object(volumes, &it, true);
+ if(v == NULL) break;
+ char const *k = ucl_object_key(v);
+ if(k != NULL) continue;
+ mapping *I = E->Volume + E->VolumeCount;
+ char *NewPosition;
+ asprintf(&NewPosition, "%s.volumes[%zu]", Position, E->VolumeCount);
+ Error = Parse_mapping(I, v, NewPosition);
+ free(NewPosition);
+ if(Error != NULL) goto error;
+ }
+ }
+ E->DevfsRuleset = ucl_object_toint(devfs);
+ return NULL;
+error:
+ Free_filesystem_configuration(E);
+ return Error;
+}
+
+char *
+Parse_configuration(configuration *E, ucl_object_t const *root, char const *Position)
+{
+ char *Error;
+ UCL_CHECK_ROOT(OBJECT);
+ {
+ char *NewPosition;
+ asprintf(&NewPosition, "%s.interfaces", Position);
+ Error =
+ Parse_interfaces_configuration(&E->Interfaces, ucl_object_lookup(root, "interfaces"), NewPosition);
+ free(NewPosition);
+ if(Error != NULL) goto error;
+ }
+ {
+ char *NewPosition;
+ asprintf(&NewPosition, "%s.filesystem", Position);
+ Error =
+ Parse_filesystem_configuration(&E->Filesystem, ucl_object_lookup(root, "filesystem"), NewPosition);
+ free(NewPosition);
+ if(Error != NULL) goto error;
+ }
+ {
+ char *NewPosition;
+ asprintf(&NewPosition, "%s.init", Position);
+ Error = Parse_string_array(&E->Init, ucl_object_lookup(root, "init"), NewPosition);
+ free(NewPosition);
+ if(Error != NULL) goto error;
+ }
+ {
+ char *NewPosition;
+ asprintf(&NewPosition, "%s.shutdown", Position);
+ Error = Parse_string_array(&E->Shutdown, ucl_object_lookup(root, "shutdown"), NewPosition);
+ free(NewPosition);
+ if(Error != NULL) goto error;
+ }
+ return NULL;
+error:
+ return Error;
+}
+
+char *
+Parse_interface(interface *E, ucl_object_t const *root, char const *Position)
+{
+ char *Error;
+ UCL_CHECK_ROOT(OBJECT);
+ {
+ char *NewPosition;
+ asprintf(&NewPosition, "%s.type", Position);
+ Error = Parse_interface_type(&E->Type, ucl_object_lookup(root, "type"), NewPosition);
+ free(NewPosition);
+ if(Error != NULL) goto error;
+ }
+ switch(E->Type)
+ {
+ case interface_type_eiface:
+ {
+ ucl_object_t const *id = ucl_object_lookup(root, "id");
+ UCL_CHECK(id, INT);
+ s64 ID = ucl_object_toint(id);
+ if(ID < 0 || ID > INT32_MAX)
+ {
+ asprintf(&Error, "%s id invalid (%ld)", Position, ID);
+ goto error;
+ }
+ E->ID = (u32)ID;
+ break;
+ }
+ case interface_type_steal: break;
+ case interface_type_COUNT:
+ default: __builtin_unreachable();
+ }
+ return NULL;
+error:
+ return Error;
+}
+
+char *
+Parse_interfaces(interfaces *E, ucl_object_t const *root, char const *Position)
+{
+ char *Error;
+ UCL_CHECK_ROOT(ARRAY);
+ E->Count = root->len;
+ E->_ = calloc(sizeof(interface_configuration), E->Count);
+ {
+ ucl_object_iter_t it = NULL;
+ for(E->Count = 0; E->Count < root->len; ++E->Count)
+ {
+ ucl_object_t const *v = ucl_iterate_object(root, &it, true);
+ if(v == NULL) break;
+ char const *k = ucl_object_key(v);
+ if(k != NULL) continue;
+ interface *I = E->_ + E->Count;
+ char *NewPosition;
+ asprintf(&NewPosition, "%s['%zu']", Position, E->Count);
+ Error = Parse_interface(I, v, NewPosition);
+ free(NewPosition);
+ if(Error != NULL) goto error;
+ }
+ }
+ return NULL;
+error:
+ Free_interfaces(E);
+ return Error;
+}
+
+char *
+Parse_data(data *E, ucl_object_t const *root, char const *Position)
+{
+ char *Error;
+ UCL_CHECK_ROOT(OBJECT);
+ ucl_object_t const *jid = ucl_object_lookup(root, "jid");
+ UCL_CHECK(jid, INT);
+ int64_t JID = ucl_object_toint(jid);
+ if(JID < 0 || JID > INT32_MAX)
+ {
+ asprintf(&Error, "%s jid invalid (%ld)", Position, JID);
+ goto error;
+ }
+ E->JID = (jid_t)JID;
+ {
+ char *NewPosition;
+ asprintf(&NewPosition, "%s.interfaces", Position);
+ Error = Parse_interfaces(&E->Interfaces, ucl_object_lookup(root, "interfaces"), NewPosition);
+ free(NewPosition);
+ if(Error != NULL) goto error;
+ }
+ return NULL;
+error:
+ return Error;
+}
+
+// SAVE
+
+void
+Save_interface(jprint_state *S, interface const *E)
+{
+ JPrintObjectBegin(S);
+ JPrintMember(S, "type");
+ JPrint_string(S, interface_type_Names[E->Type]);
+ switch(E->Type)
+ {
+ case interface_type_eiface:
+ {
+ JPrintMember(S, "id");
+ JPrint_ssize_t(S, E->ID);
+ break;
+ }
+ case interface_type_steal: break;
+ case interface_type_COUNT:
+ default: __builtin_unreachable();
+ }
+ JPrintObjectEnd(S);
+}
+
+void
+Save_interfaces(jprint_state *S, interfaces const *E)
+{
+ JPrintArrayBegin(S);
+ for(size_t i = 0; i < E->Count; ++i) Save_interface(S, E->_ + i);
+ JPrintArrayEnd(S);
+}
+
+void
+Save_data(jprint_state *S, data const *E)
+{
+ JPrintObjectBegin(S);
+ JPrintMember(S, "jid");
+ JPrint_ssize_t(S, E->JID);
+ JPrintMember(S, "interfaces");
+ Save_interfaces(S, &E->Interfaces);
+ JPrintObjectEnd(S);
+}