ubusd: fix build on non-linux systems without peercred support
[project/ubus.git] / ubusd_obj.c
index 7ae9b5f..914de05 100644 (file)
@@ -58,6 +58,9 @@ static struct ubus_object_type *ubus_create_obj_type(struct blob_attr *sig)
        int rem;
 
        type = calloc(1, sizeof(*type));
+       if (!type)
+               return NULL;
+
        type->refcount = 1;
 
        if (!ubus_alloc_id(&obj_types, &type->id, 0))
@@ -112,8 +115,8 @@ struct ubus_object *ubusd_create_object_internal(struct ubus_object_type *type,
        obj->type = type;
        INIT_LIST_HEAD(&obj->list);
        INIT_LIST_HEAD(&obj->events);
-       INIT_LIST_HEAD(&obj->watchers);
-       INIT_LIST_HEAD(&obj->watched);
+       INIT_LIST_HEAD(&obj->subscribers);
+       INIT_LIST_HEAD(&obj->target_list);
        if (type)
                type->refcount++;
 
@@ -142,6 +145,9 @@ struct ubus_object *ubusd_create_object(struct ubus_client *cl, struct blob_attr
                return NULL;
 
        if (attr[UBUS_ATTR_OBJPATH]) {
+               if (ubusd_acl_check(cl, blob_data(attr[UBUS_ATTR_OBJPATH]), NULL, UBUS_ACL_PUBLISH))
+                       goto free;
+
                obj->path.key = strdup(blob_data(attr[UBUS_ATTR_OBJPATH]));
                if (!obj->path.key)
                        goto free;
@@ -164,37 +170,45 @@ free:
        return NULL;
 }
 
-void ubus_watch_new(struct ubus_object *obj, struct ubus_object *target, const char *method)
+void ubus_subscribe(struct ubus_object *obj, struct ubus_object *target)
 {
-       struct ubus_watch *w;
+       struct ubus_subscription *s;
+       bool first = list_empty(&target->subscribers);
 
-       w = calloc(1, sizeof(*w) + strlen(method) + 1);
-       if (!w)
+       s = calloc(1, sizeof(*s));
+       if (!s)
                return;
 
-       w->watcher = obj;
-       w->watched = target;
-       list_add(&w->watcher_list, &target->watchers);
-       list_add(&w->watched_list, &obj->watched);
-       strcpy(w->method, method);
+       s->subscriber = obj;
+       s->target = target;
+       list_add(&s->list, &target->subscribers);
+       list_add(&s->target_list, &obj->target_list);
+
+       if (first)
+               ubus_notify_subscription(target);
 }
 
-void ubus_watch_free(struct ubus_watch *w)
+void ubus_unsubscribe(struct ubus_subscription *s)
 {
-       list_del(&w->watcher_list);
-       list_del(&w->watched_list);
-       free(w);
+       struct ubus_object *obj = s->target;
+
+       list_del(&s->list);
+       list_del(&s->target_list);
+       free(s);
+
+       if (list_empty(&obj->subscribers))
+               ubus_notify_subscription(obj);
 }
 
 void ubusd_free_object(struct ubus_object *obj)
 {
-       struct ubus_watch *w, *tmp;
+       struct ubus_subscription *s, *tmp;
 
-       list_for_each_entry_safe(w, tmp, &obj->watched, watched_list) {
-               ubus_watch_free(w);
+       list_for_each_entry_safe(s, tmp, &obj->target_list, target_list) {
+               ubus_unsubscribe(s);
        }
-       list_for_each_entry_safe(w, tmp, &obj->watchers, watcher_list) {
-               ubus_proto_notify_watch(w);
+       list_for_each_entry_safe(s, tmp, &obj->subscribers, list) {
+               ubus_notify_unsubscribe(s);
        }
 
        ubusd_event_cleanup_object(obj);
@@ -211,10 +225,11 @@ void ubusd_free_object(struct ubus_object *obj)
        free(obj);
 }
 
-static void __init ubusd_obj_init(void)
+static void __constructor ubusd_obj_init(void)
 {
        ubus_init_id_tree(&objects);
        ubus_init_id_tree(&obj_types);
        ubus_init_string_tree(&path, false);
        ubusd_event_init();
+       ubusd_acl_init();
 }