+ *e = uci_lookup_list(list, name);
+ if (!*e)
+ UCI_THROW(ctx, UCI_ERR_NOTFOUND);
+
+ return 0;
+}
+
+int
+uci_lookup_ptr(struct uci_context *ctx, struct uci_ptr *ptr, char *str, bool extended)
+{
+ struct uci_element *e;
+
+ UCI_HANDLE_ERR(ctx);
+ UCI_ASSERT(ctx, ptr != NULL);
+
+ if (str)
+ UCI_INTERNAL(uci_parse_ptr, ctx, ptr, str);
+
+ ptr->flags |= UCI_LOOKUP_DONE;
+
+ /* look up the package first */
+ if (ptr->p)
+ e = &ptr->p->e;
+ else
+ e = uci_lookup_list(&ctx->root, ptr->package);
+
+ if (!e) {
+ UCI_INTERNAL(uci_load, ctx, ptr->package, &ptr->p);
+ if (!ptr->p)
+ goto notfound;
+ ptr->last = &ptr->p->e;
+ } else {
+ ptr->p = uci_to_package(e);
+ ptr->last = e;
+ }
+
+ if (!ptr->section && !ptr->s)
+ goto complete;
+
+ /* if the section name validates as a regular name, pass through
+ * to the regular uci_lookup function call */
+ if (ptr->s) {
+ e = &ptr->s->e;
+ } else if (ptr->flags & UCI_LOOKUP_EXTENDED) {
+ if (extended)
+ e = uci_lookup_ext_section(ctx, ptr);
+ else
+ UCI_THROW(ctx, UCI_ERR_INVAL);
+ } else {
+ e = uci_lookup_list(&ptr->p->sections, ptr->section);
+ }
+
+ if (!e)
+ goto abort;
+
+ ptr->last = e;
+ ptr->s = uci_to_section(e);
+
+ if (ptr->option) {
+ e = uci_lookup_list(&ptr->s->options, ptr->option);
+ if (!e)
+ goto abort;
+
+ ptr->o = uci_to_option(e);
+ ptr->last = e;
+ }
+
+complete:
+ ptr->flags |= UCI_LOOKUP_COMPLETE;
+abort:
+ return 0;
+
+notfound:
+ UCI_THROW(ctx, UCI_ERR_NOTFOUND);
+ return 0;
+}
+
+__private struct uci_element *
+uci_expand_ptr(struct uci_context *ctx, struct uci_ptr *ptr, bool complete)
+{
+ UCI_ASSERT(ctx, ptr != NULL);
+
+ if (!(ptr->flags & UCI_LOOKUP_DONE))
+ UCI_INTERNAL(uci_lookup_ptr, ctx, ptr, NULL, 1);
+ if (complete && !(ptr->flags & UCI_LOOKUP_COMPLETE))
+ UCI_THROW(ctx, UCI_ERR_NOTFOUND);
+ UCI_ASSERT(ctx, ptr->p != NULL);
+
+ /* fill in missing string info */
+ if (ptr->p && !ptr->package)
+ ptr->package = ptr->p->e.name;
+ if (ptr->s && !ptr->section)
+ ptr->section = ptr->s->e.name;
+ if (ptr->o && !ptr->option)
+ ptr->option = ptr->o->e.name;
+
+ if (ptr->o)
+ return &ptr->o->e;
+ if (ptr->s)
+ return &ptr->s->e;
+ if (ptr->p)
+ return &ptr->p->e;
+ else
+ return NULL;
+}
+
+static void uci_add_element_list(struct uci_context *ctx, struct uci_ptr *ptr, bool internal)
+{
+ struct uci_element *e;
+ struct uci_package *p;
+
+ p = ptr->p;
+ if (!internal && p->has_delta)
+ uci_add_delta(ctx, &p->delta, UCI_CMD_LIST_ADD, ptr->section, ptr->option, ptr->value);
+
+ e = uci_alloc_generic(ctx, UCI_TYPE_ITEM, ptr->value, sizeof(struct uci_option));
+ uci_list_add(&ptr->o->v.list, &e->list);
+}
+
+int uci_rename(struct uci_context *ctx, struct uci_ptr *ptr)
+{
+ /* NB: UCI_INTERNAL use means without delta tracking */
+ bool internal = ctx && ctx->internal;
+ struct uci_element *e;
+ struct uci_package *p;
+ char *n;
+
+ UCI_HANDLE_ERR(ctx);
+
+ e = uci_expand_ptr(ctx, ptr, true);
+ p = ptr->p;
+
+ UCI_ASSERT(ctx, ptr->s);
+ UCI_ASSERT(ctx, ptr->value);
+
+ if (!internal && p->has_delta)
+ uci_add_delta(ctx, &p->delta, UCI_CMD_RENAME, ptr->section, ptr->option, ptr->value);