@@ -547,6 +547,7 @@ void lu_read_state(void)
xprintf("live-update: ignore transaction record\n");
break;
case XS_STATE_TYPE_NODE:
+ read_state_node(ctx, head + 1);
break;
default:
xprintf("live-update: unknown state record %08x\n",
@@ -972,13 +972,30 @@ static char *basename(const char *name)
return strrchr(name, '/') + 1;
}
-static struct node *construct_node(struct connection *conn, const void *ctx,
- const char *name)
+static int add_child(const void *ctx, struct node *parent, const char *name)
{
const char *base;
unsigned int baselen;
+ char *children;
+
+ base = basename(name);
+ baselen = strlen(base) + 1;
+ children = talloc_array(ctx, char, parent->childlen + baselen);
+ if (!children)
+ return ENOMEM;
+ memcpy(children, parent->children, parent->childlen);
+ memcpy(children + parent->childlen, base, baselen);
+ parent->children = children;
+ parent->childlen += baselen;
+
+ return 0;
+}
+
+static struct node *construct_node(struct connection *conn, const void *ctx,
+ const char *name)
+{
struct node *parent, *node;
- char *children, *parentname = get_parent(ctx, name);
+ char *parentname = get_parent(ctx, name);
if (!parentname)
return NULL;
@@ -991,15 +1008,8 @@ static struct node *construct_node(struct connection *conn, const void *ctx,
return NULL;
/* Add child to parent. */
- base = basename(name);
- baselen = strlen(base) + 1;
- children = talloc_array(ctx, char, parent->childlen + baselen);
- if (!children)
+ if (add_child(ctx, parent, name))
goto nomem;
- memcpy(children, parent->children, parent->childlen);
- memcpy(children + parent->childlen, base, baselen);
- parent->children = children;
- parent->childlen += baselen;
/* Allocate node */
node = talloc(ctx, struct node);
@@ -2612,6 +2622,79 @@ void read_state_buffered_data(const void *ctx, struct connection *conn,
}
}
+void read_state_node(const void *ctx, const void *state)
+{
+ const struct xs_state_node *sn = state;
+ struct node *node, *parent;
+ TDB_DATA key;
+ char *name, *parentname;
+ unsigned int i;
+ struct connection conn = { .id = priv_domid };
+
+ name = (char *)(sn->perms + sn->perm_n);
+ node = talloc(ctx, struct node);
+ if (!node)
+ barf("allocation error restoring node");
+
+ node->name = name;
+ node->generation = ++generation;
+ node->datalen = sn->data_len;
+ node->data = name + sn->path_len;
+ node->childlen = 0;
+ node->children = NULL;
+ node->perms.num = sn->perm_n;
+ node->perms.p = talloc_array(node, struct xs_permissions,
+ node->perms.num);
+ if (!node->perms.p)
+ barf("allocation error restoring node");
+ for (i = 0; i < node->perms.num; i++) {
+ switch (sn->perms[i].access) {
+ case 'r':
+ node->perms.p[i].perms = XS_PERM_READ;
+ break;
+ case 'w':
+ node->perms.p[i].perms = XS_PERM_WRITE;
+ break;
+ case 'b':
+ node->perms.p[i].perms = XS_PERM_READ | XS_PERM_WRITE;
+ break;
+ default:
+ node->perms.p[i].perms = XS_PERM_NONE;
+ break;
+ }
+ if (sn->perms[i].flags & XS_STATE_NODE_PERM_IGNORE)
+ node->perms.p[i].perms |= XS_PERM_IGNORE;
+ node->perms.p[i].id = sn->perms[i].domid;
+ }
+
+ if (strstarts(name, "@")) {
+ set_perms_special(&conn, name, &node->perms);
+ talloc_free(node);
+ return;
+ }
+
+ parentname = get_parent(node, name);
+ if (!parentname)
+ barf("allocation error restoring node");
+ parent = read_node(NULL, node, parentname);
+ if (!parent)
+ barf("read parent error restoring node");
+
+ if (add_child(node, parent, name))
+ barf("allocation error restoring node");
+
+ set_tdb_key(parentname, &key);
+ if (write_node_raw(NULL, &key, parent, true))
+ barf("write parent error restoring node");
+
+ set_tdb_key(name, &key);
+ if (write_node_raw(NULL, &key, node, true))
+ barf("write node error restoring node");
+ domain_entry_inc(&conn, node);
+
+ talloc_free(node);
+}
+
/*
* Local variables:
* mode: C
@@ -276,6 +276,7 @@ const char *dump_state_node_perms(FILE *fp, struct xs_state_node *sn,
void read_state_global(const void *ctx, const void *state);
void read_state_buffered_data(const void *ctx, struct connection *conn,
const struct xs_state_connection *sc);
+void read_state_node(const void *ctx, const void *state);
#endif /* _XENSTORED_CORE_H */