+instance_netdev_cmp(struct blobmsg_list_node *l1, struct blobmsg_list_node *l2)
+{
+ struct instance_netdev *n1 = container_of(l1, struct instance_netdev, node);
+ struct instance_netdev *n2 = container_of(l2, struct instance_netdev, node);
+
+ return n1->ifindex == n2->ifindex;
+}
+
+static void
+instance_netdev_update(struct blobmsg_list_node *l)
+{
+ struct instance_netdev *n = container_of(l, struct instance_netdev, node);
+
+ n->ifindex = if_nametoindex(n->node.avl.key);
+}
+
+static bool
+instance_file_cmp(struct blobmsg_list_node *l1, struct blobmsg_list_node *l2)
+{
+ struct instance_file *f1 = container_of(l1, struct instance_file, node);
+ struct instance_file *f2 = container_of(l2, struct instance_file, node);
+
+ return !memcmp(f1->md5, f2->md5, sizeof(f1->md5));
+}
+
+static void
+instance_file_update(struct blobmsg_list_node *l)
+{
+ struct instance_file *f = container_of(l, struct instance_file, node);
+ md5_ctx_t md5;
+ char buf[256];
+ int len, fd;
+
+ memset(f->md5, 0, sizeof(f->md5));
+
+ fd = open(l->avl.key, O_RDONLY);
+ if (fd < 0)
+ return;
+
+ md5_begin(&md5);
+ do {
+ len = read(fd, buf, sizeof(buf));
+ if (len < 0) {
+ if (errno == EINTR)
+ continue;
+
+ break;
+ }
+ if (!len)
+ break;
+
+ md5_hash(buf, len, &md5);
+ } while(1);
+
+ md5_end(f->md5, &md5);
+ close(fd);
+}
+
+static bool
+instance_fill_array(struct blobmsg_list *l, struct blob_attr *cur, blobmsg_update_cb cb, bool array)
+{
+ struct blobmsg_list_node *node;
+
+ if (!cur)
+ return true;
+
+ if (!blobmsg_check_attr_list(cur, BLOBMSG_TYPE_STRING))
+ return false;
+
+ blobmsg_list_fill(l, blobmsg_data(cur), blobmsg_data_len(cur), array);
+ if (cb) {
+ blobmsg_list_for_each(l, node)
+ cb(node);
+ }
+ return true;
+}
+
+static bool