#include #define NAMESPACE_CAST(p) OBJECT_C_CAST(struct object_namespace, ns_base, &ns_type, p) static struct object_type ns_type; static struct object_namespace *global_ns; struct object_namespace { /* root directory set object */ struct object ns_base; struct object *ns_root; }; static kern_status_t ns_query_name(struct object *obj, char out[OBJECT_NAME_MAX]) { out[0] = '/'; out[1] = 0; return KERN_OK; } static kern_status_t ns_get_child_at(struct object *obj, size_t at, struct object **out) { struct object_namespace *ns = NAMESPACE_CAST(obj); return object_get_child_at(ns->ns_root, at, out); } static kern_status_t ns_get_child_named(struct object *obj, const char *name, struct object **out) { struct object_namespace *ns = NAMESPACE_CAST(obj); return object_get_child_named(ns->ns_root, name, out); } static struct object_type ns_type = { .ob_name = "namespace", .ob_size = sizeof(struct object_namespace), .ob_header_offset = offsetof(struct object_namespace, ns_base), .ob_ops = { .query_name = ns_query_name, .get_named = ns_get_child_named, .get_at = ns_get_child_at, }, }; void init_global_namespace(void) { object_type_register(&ns_type); global_ns = object_namespace_create(); } struct object_namespace *global_namespace(void) { return global_ns; } struct object_namespace *object_namespace_create(void) { struct object *ns_object = object_create(&ns_type); struct object_namespace *ns = NAMESPACE_CAST(ns_object); ns->ns_root = set_create("/"); return ns; } kern_status_t object_namespace_get_object(struct object_namespace *ns, const char *path, struct object **out) { 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; } struct object *ns_header(struct object_namespace *ns) { return &ns->ns_base; } kern_status_t object_publish(struct object_namespace *ns, const char *path, struct object *obj) { if (*path != '/') { return KERN_INVALID_ARGUMENT; } while (*path == '/') { path++; } size_t path_len = strlen(path); if (path_len == 0) { return set_add_object(ns->ns_root, obj); } 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); struct object *cur = ns->ns_root; unsigned long flags; while (tok) { object_lock(cur, &flags); struct object *next; kern_status_t status = object_get_child_named(cur, tok, &next); if (status == KERN_NO_ENTRY) { next = set_create(tok); if (!next) { object_unlock(cur, flags); kfree(rpath); return KERN_NO_MEMORY; } status = set_add_object(cur, next); } if (status != KERN_OK) { object_unlock(cur, flags); kfree(rpath); return status; } object_unlock(cur, flags); cur = next; tok = strtok_r(NULL, "/", &sp); } kfree(rpath); return set_add_object(cur, obj); } kern_status_t object_unpublish(struct object_namespace *ns, struct object *obj) { return KERN_OK; }