| 99 | } |
| 100 | |
| 101 | static struct command_result *json_datastore(struct command *cmd, |
| 102 | const char *buffer, |
| 103 | const jsmntok_t *obj UNNEEDED, |
| 104 | const jsmntok_t *params) |
| 105 | { |
| 106 | struct json_stream *response; |
| 107 | const char **key, *strdata, **k; |
| 108 | u8 *data; |
| 109 | const u8 *prevdata; |
| 110 | enum ds_mode *mode; |
| 111 | u64 *generation, actual_gen; |
| 112 | struct db_stmt *stmt; |
| 113 | |
| 114 | if (!param_check(cmd, buffer, params, |
| 115 | p_req("key", param_list_or_string, &key), |
| 116 | p_opt("string", param_escaped_string, &strdata), |
| 117 | p_opt("hex", param_bin_from_hex, &data), |
| 118 | p_opt_def("mode", param_mode, &mode, DS_MUST_NOT_EXIST), |
| 119 | p_opt("generation", param_u64, &generation), |
| 120 | NULL)) |
| 121 | return command_param_failed(); |
| 122 | |
| 123 | if (strdata) { |
| 124 | if (data) |
| 125 | return command_fail(cmd, JSONRPC2_INVALID_PARAMS, |
| 126 | "Cannot have both hex and string"); |
| 127 | data = tal_dup_arr(cmd, u8, (u8 *)strdata, strlen(strdata), 0); |
| 128 | } else { |
| 129 | if (!data) |
| 130 | return command_fail(cmd, JSONRPC2_INVALID_PARAMS, |
| 131 | "Must have either hex or string"); |
| 132 | } |
| 133 | |
| 134 | if (generation && !(*mode & DS_MUST_EXIST)) |
| 135 | return command_fail(cmd, JSONRPC2_INVALID_PARAMS, |
| 136 | "generation only valid with must-replace" |
| 137 | " or must-append"); |
| 138 | |
| 139 | /* Fetch, and make sure we don't have children! */ |
| 140 | stmt = wallet_datastore_first(cmd, cmd->ld->wallet, key, |
| 141 | &k, &prevdata, &actual_gen); |
| 142 | tal_free(stmt); |
| 143 | |
| 144 | /* We use prevdata as a "does it exist?" flag */ |
| 145 | if (!stmt) |
| 146 | prevdata = NULL; |
| 147 | else if (!datastore_key_eq(k, key)) { |
| 148 | prevdata = tal_free(prevdata); |
| 149 | /* Make sure we don't have a child! */ |
| 150 | if (datastore_key_startswith(k, key)) |
| 151 | return command_fail(cmd, DATASTORE_UPDATE_HAS_CHILDREN, |
| 152 | "Key has children already"); |
| 153 | } |
| 154 | |
| 155 | /* We have to make sure that parents don't exist. */ |
| 156 | if (!prevdata) { |
| 157 | for (size_t i = 1; i < tal_count(key); i++) { |
| 158 | const char **parent; |
nothing calls this directly
no test coverage detected