Skip to content

Commit

Permalink
C: teach <install> to cope with 'install_done' arriving before 'ok'
Browse files Browse the repository at this point in the history
In releases built after 2014, it is possible for the 'install_done'
event to arrive before the 'ok' at the end of an installation. This
patch teaches the C install code to handle that gracefully.
  • Loading branch information
matthiasl committed Feb 14, 2014
1 parent e1d0a92 commit c084b89
Showing 1 changed file with 48 additions and 37 deletions.
85 changes: 48 additions & 37 deletions c/gth_apilib.c
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -311,20 +311,40 @@ int gth_wait_for_accept(int listen_socket)
return data_socket; return data_socket;
} }


// We're expecting an install-complete event, wait for it // Return 1 if the given resp is an 'install_done' event, 0 otherwise.
// static int is_install_done_event(GTH_resp *resp)
{
GTH_resp *child;

if (resp->type != GTH_RESP_EVENT)
return 0;

assert(resp->n_children == 1);

child = resp->children + 0;

if (child->type == GTH_RESP_INFO) {
if (!strcmp("install_done", attribute_value(child, "reason"))) {
return 1;
}
}

return 0;
}


// Return: 0 on success // Return: 0 on success
static int gth_wait_for_install_complete(GTH_api *api) static int gth_wait_for_install_complete(GTH_api *api, int need_install_done)
{ {
char buffer[MAX_COMMAND]; char buffer[MAX_COMMAND];
int result; int result;
GTH_resp *resp = 0; GTH_resp *resp = 0;
int looking_for_ok = 1;
int looking_for_install_done = need_install_done;


assert(api); assert(api);


for (;;) { for (;;) {
GTH_resp *child;

result = next_api_response(api, buffer, sizeof(buffer)); result = next_api_response(api, buffer, sizeof(buffer));
if (result != 0) { if (result != 0) {
return -1; return -1;
Expand All @@ -335,25 +355,28 @@ static int gth_wait_for_install_complete(GTH_api *api)
if (resp == 0) { if (resp == 0) {
return -1; return -1;
} }
assert(resp->type == GTH_RESP_EVENT);
assert(resp->n_children == 1);

child = resp->children + 0;


if (child->type == GTH_RESP_INFO) { if (is_install_done_event(resp))
if (!strcmp("install_done", attribute_value(child, "reason"))) { looking_for_install_done = 0;
gth_free_resp(resp); else
return 0; {
} assert(api->event_handler);
else { if (resp->type == GTH_RESP_EVENT)
gth_print_tree(resp); (*api->event_handler)(api, resp);
gth_free_resp(resp); else if (resp->type == GTH_RESP_OK)
return -1; looking_for_ok = 0;
else
{
gth_print_tree(resp);
gth_free_resp(resp);
return -1;
}
} }
}


assert(api->event_handler); gth_free_resp(resp);
(*api->event_handler)(api, resp);
if (!looking_for_install_done && !looking_for_ok)
return 0;
} }


return 0; return 0;
Expand Down Expand Up @@ -414,30 +437,18 @@ int gth_install(GTH_api *api,
const int length) const int length)
{ {
char buffer[MAX_COMMAND]; char buffer[MAX_COMMAND];
GTH_resp *resp; int result;
int is_firmware_install = !strcmp(type, "binary/filesystem");


assert(api); assert(api);


snprintf(buffer, MAX_COMMAND, "<install name='%s'/>", name); snprintf(buffer, MAX_COMMAND, "<install name='%s'/>", name);
api_write(api, buffer); api_write(api, buffer);
api_write_non_xml(api->fd, type, data, length); api_write_non_xml(api->fd, type, data, length);


if (check_api_response(api, GTH_RESP_OK, &resp)) result = gth_wait_for_install_complete(api, is_firmware_install);
{
if (resp)
{
gth_print_tree(resp);
gth_free_resp(resp);
}
return -1;
}

// Upgrades send an <info> when they're really complete.
if (!strcmp(type, "binary/filesystem")) {
gth_wait_for_install_complete(api);
}


return 0; return result;
} }


int gth_new_cas_r2_mfc_detector(GTH_api *api, int gth_new_cas_r2_mfc_detector(GTH_api *api,
Expand Down

0 comments on commit c084b89

Please sign in to comment.