From 8c87e787979775d674a4080a8969ad2cd528aefc Mon Sep 17 00:00:00 2001 From: Max Wash Date: Sat, 25 Feb 2023 17:57:53 +0000 Subject: [PATCH] obj: add more set and namespace functions --- include/socks/compiler.h | 7 ++++ include/socks/object.h | 29 ++++++++++++- include/socks/status.h | 1 + include/socks/util.h | 1 + obj/namespace.c | 88 ++++++++++++++++++++++++++++++++++++++-- obj/object.c | 41 +++++++++++++++++++ obj/set.c | 86 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 248 insertions(+), 5 deletions(-) diff --git a/include/socks/compiler.h b/include/socks/compiler.h index 61044bb..bcdba79 100644 --- a/include/socks/compiler.h +++ b/include/socks/compiler.h @@ -1,9 +1,16 @@ #ifndef SOCKS_COMPILER_H_ #define SOCKS_COMPILER_H_ +#undef __used #define __used __attribute__((used)) + +#undef __packed #define __packed __attribute__((packed)) + +#undef __section #define __section(name) __attribute__((section(name))) + +#undef __aligned #define __aligned(x) __attribute__((aligned(x))) #endif diff --git a/include/socks/object.h b/include/socks/object.h index d26a9ca..8b3588e 100644 --- a/include/socks/object.h +++ b/include/socks/object.h @@ -7,8 +7,10 @@ #include #define OBJECT_MAGIC 0xBADDCAFE +#define OBJECT_NAME_MAX 64 struct object; +struct object_attrib; typedef enum object_type_flags { OBJTYPE_INIT = 0x01u, @@ -18,27 +20,38 @@ typedef struct object_ops { kern_status_t(*open)(struct object *obj); kern_status_t(*close)(struct object *obj); kern_status_t(*delete)(struct object *obj); - kern_status_t(*query_name)(struct object *obj, char *out, size_t max); + kern_status_t(*query_name)(struct object *obj, char out[OBJECT_NAME_MAX]); kern_status_t(*parse)(struct object *obj, const char *path, struct object **out); - kern_status_t(*get_name)(struct object *obj, const char *name, struct object **out); + kern_status_t(*get_named)(struct object *obj, const char *name, struct object **out); kern_status_t(*get_at)(struct object *obj, size_t at, struct object **out); + kern_status_t(*read_attrib)(struct object *obj, struct object_attrib *attrib, char *out, size_t max, size_t *r); + kern_status_t(*write_attrib)(struct object *obj, struct object_attrib *attrib, const char *s, size_t len, size_t *r); } object_ops_t; +typedef struct object_attrib { + char *a_name; + queue_entry_t a_list; +} object_attrib_t; + typedef struct object_type { object_type_flags_t ob_flags; char ob_name[32]; unsigned int ob_size; vm_cache_t ob_cache; queue_entry_t ob_list; + queue_t ob_attrib; const object_ops_t *ob_ops; } object_type_t; typedef struct object { uint32_t ob_magic; + struct object *ob_parent; object_type_t *ob_type; spin_lock_t ob_lock; unsigned int ob_refcount; unsigned int ob_handles; + queue_t ob_attrib; + queue_entry_t ob_list; } __aligned(sizeof(long)) object_t; typedef struct object_namespace object_namespace_t; @@ -56,12 +69,24 @@ extern kern_status_t object_unpublish(object_namespace_t *ns, object_t *obj); extern object_t *object_create(object_type_t *type); extern object_t *object_ref(object_t *obj); extern void object_deref(object_t *obj); +extern void object_lock(object_t *obj, unsigned long *flags); +extern void object_unlock(object_t *obj, unsigned long flags); extern void *object_data(object_t *obj); extern object_t *object_header(void *p); static inline kern_status_t object_get(const char *path, object_t **out) { return object_namespace_get_object(global_namespace(), path, out); } +extern object_t *object_get_child_named(object_t *obj, const char *name); +extern object_t *object_get_child_at(object_t *obj, size_t at); +extern kern_status_t object_query_name(object_t *obj, char name[OBJECT_NAME_MAX]); + +extern object_t *set_create(const char *name); +extern kern_status_t set_lock(object_t *obj, unsigned long *flags); +extern kern_status_t set_unlock(object_t *obj, unsigned long flags); +extern kern_status_t set_add_object(object_t *set, object_t *obj); +extern kern_status_t set_remove_object(object_t *set, object_t *obj); +extern bool object_is_set(object_t *obj); extern void init_set_objects(void); extern void init_global_namespace(void); diff --git a/include/socks/status.h b/include/socks/status.h index 7aeeb21..1ff7a1e 100644 --- a/include/socks/status.h +++ b/include/socks/status.h @@ -8,5 +8,6 @@ typedef unsigned int kern_status_t; #define KERN_NAME_EXISTS (2) #define KERN_INVALID_ARGUMENT (3) #define KERN_UNSUPPORTED (4) +#define KERN_NO_MEMORY (5) #endif diff --git a/include/socks/util.h b/include/socks/util.h index 3fd1ff5..6ab5748 100644 --- a/include/socks/util.h +++ b/include/socks/util.h @@ -2,6 +2,7 @@ #define SOCKS_UTIL_H_ #include +#include #include extern void data_size_to_string(size_t value, char *out, size_t outsz); diff --git a/obj/namespace.c b/obj/namespace.c index 7c16e72..a03d307 100644 --- a/obj/namespace.c +++ b/obj/namespace.c @@ -2,6 +2,7 @@ #include struct object_namespace { + /* root directory set object */ object_t *ns_root; }; @@ -26,8 +27,10 @@ object_namespace_t *global_namespace(void) object_namespace_t *object_namespace_create(void) { - object_t *ns = object_create(&ns_type); - return object_data(ns); + object_t *ns_object = object_create(&ns_type); + object_namespace_t *ns = object_data(ns_object); + ns->ns_root = set_create("/"); + return ns; } kern_status_t object_namespace_get_object(object_namespace_t *ns, const char *path, object_t **out) @@ -35,9 +38,88 @@ kern_status_t object_namespace_get_object(object_namespace_t *ns, const char *pa return KERN_OK; } +static void cleanup_object_path(char *path, size_t len, size_t *parts) +{ + while (path[len - 1] == '/') { + path[--len] = 0; + } + + size_t final_len = len; + *parts = 0; + + int slashes = 0; + for (int i = 0; path[i]; i++) { + if (path[i] == '/') { + slashes++; + continue; + } + + if (slashes < 1) { + continue; + } + + char *from = path + i; + char *to = path + i - slashes + 1; + int count = len - i; + memmove(to, from, count); + final_len -= (slashes - 1); + slashes = 0; + (*parts)++; + } + + path[final_len] = 0; +} + kern_status_t object_publish(object_namespace_t *ns, const char *path, object_t *obj) { - return KERN_OK; + if (*path != '/') { + return KERN_INVALID_ARGUMENT; + } + + while (*path == '/') { + path++; + } + + size_t path_len = strlen(path); + if (path_len == 0) { + return KERN_INVALID_ARGUMENT; + } + + size_t parts = 0; + char *rpath = kmalloc(path_len, 0); + if (!rpath) { + return KERN_NO_MEMORY; + } + + memcpy(rpath, path, path_len); + cleanup_object_path(rpath, path_len, &parts); + + char *sp; + char *tok = strtok_r(rpath, "/", &sp); + object_t *cur = ns->ns_root; + + unsigned long flags; + while (tok) { + set_lock(cur, &flags); + + object_t *next = object_get_child_named(cur, tok); + if (!next) { + next = set_create(tok); + if (!next) { + kfree(rpath); + return KERN_NO_MEMORY; + } + + set_add_object(cur, next); + } + + set_unlock(cur, flags); + cur = next; + } + + kfree(rpath); + + return set_add_object(cur, obj); } kern_status_t object_unpublish(object_namespace_t *ns, object_t *obj) diff --git a/obj/object.c b/obj/object.c index 8a2b446..d9f751f 100644 --- a/obj/object.c +++ b/obj/object.c @@ -93,6 +93,16 @@ void object_deref(object_t *obj) spin_unlock_irqrestore(&obj->ob_lock, flags); } +void object_lock(object_t *obj, unsigned long *flags) +{ + spin_lock_irqsave(&obj->ob_lock, flags); +} + +void object_unlock(object_t *obj, unsigned long flags) +{ + spin_unlock_irqrestore(&obj->ob_lock, flags); +} + void *object_data(object_t *obj) { return (char *)obj + sizeof *obj; @@ -107,3 +117,34 @@ object_t *object_header(void *p) return obj; } + +object_t *object_get_child_named(object_t *obj, const char *name) +{ + object_t *out = NULL; + + if (HAS_OP(obj, get_named)) { + obj->ob_type->ob_ops->get_named(obj, name, &out); + } + + return out; +} + +object_t *object_get_child_at(object_t *obj, size_t at) +{ + object_t *out = NULL; + + if (HAS_OP(obj, get_at)) { + obj->ob_type->ob_ops->get_at(obj, at, &out); + } + + return out; +} + +kern_status_t object_query_name(object_t *obj, char name[OBJECT_NAME_MAX]) +{ + if (HAS_OP(obj, query_name)) { + return obj->ob_type->ob_ops->query_name(obj, name); + } + + return KERN_UNSUPPORTED; +} diff --git a/obj/set.c b/obj/set.c index 2a8d2c0..b46d375 100644 --- a/obj/set.c +++ b/obj/set.c @@ -2,6 +2,7 @@ struct set { queue_t s_list; + char s_name[OBJECT_NAME_MAX]; spin_lock_t s_lock; }; @@ -14,3 +15,88 @@ void init_set_objects(void) { object_type_register(&set_type); } + +object_t *set_create(const char *name) +{ + object_t *set_obj = object_create(&set_type); + if (!set_obj) { + return NULL; + } + + struct set *set = object_data(set_obj); + set->s_list = QUEUE_INIT; + set->s_lock = SPIN_LOCK_INIT; + strncpy(set->s_name, name, sizeof set->s_name - 1); + set->s_name[sizeof set->s_name - 1] = 0; + + return set_obj; +} + +kern_status_t set_lock(object_t *obj, unsigned long *flags) +{ + if (!object_is_set(obj)) { + return KERN_INVALID_ARGUMENT; + } + + struct set *set = object_data(obj); + spin_lock_irqsave(&set->s_lock, flags); + + return KERN_OK; +} + +kern_status_t set_unlock(object_t *obj, unsigned long flags) +{ + if (!object_is_set(obj)) { + return KERN_INVALID_ARGUMENT; + } + + struct set *set = object_data(obj); + spin_unlock_irqrestore(&set->s_lock, flags); + + return KERN_OK; +} + +kern_status_t set_add_object(object_t *set_obj, object_t *obj) +{ + if (!object_is_set(set_obj)) { + return KERN_INVALID_ARGUMENT; + } + + struct set *set = object_data(set_obj); + + char child_name[OBJECT_NAME_MAX]; + char obj_name[OBJECT_NAME_MAX]; + + kern_status_t status = object_query_name(obj, obj_name); + if (status != KERN_OK) { + return status; + } + + queue_foreach (object_t, child, &set->s_list, ob_list) { + object_query_name(child, child_name); + + if (!strcmp(child_name, obj_name)) { + return KERN_NAME_EXISTS; + } + } + + queue_push_back(&set->s_list, &obj->ob_list); + return KERN_OK; +} + +kern_status_t set_remove_object(object_t *set_obj, object_t *obj) +{ + if (!object_is_set(set_obj)) { + return KERN_INVALID_ARGUMENT; + } + + struct set *set = object_data(set_obj); + queue_delete(&set->s_list, &obj->ob_list); + + return KERN_OK; +} + +bool object_is_set(object_t *obj) +{ + return obj->ob_type == &set_type; +}