pmix_status_t pmix_bfrop_unpack_string(pmix_buffer_t *buffer, void *dest, int32_t *num_vals, pmix_data_type_t type) { pmix_status_t ret; int32_t i, len, n=1; char **sdest = (char**) dest; for (i = 0; i < (*num_vals); ++i) { if (PMIX_SUCCESS != (ret = pmix_bfrop_unpack_int32(buffer, &len, &n, PMIX_INT32))) { return ret; } if (0 == len) { /* zero-length string - unpack the NULL */ sdest[i] = NULL; } else { sdest[i] = (char*)malloc(len); if (NULL == sdest[i]) { return PMIX_ERR_OUT_OF_RESOURCE; } if (PMIX_SUCCESS != (ret = pmix_bfrop_unpack_byte(buffer, sdest[i], &len, PMIX_BYTE))) { return ret; } } } return PMIX_SUCCESS; }
pmix_status_t pmix_bfrop_unpack_status(pmix_buffer_t *buffer, void *dest, int32_t *num_vals, pmix_data_type_t type) { pmix_output_verbose(20, pmix_globals.debug_output, "pmix_bfrop_unpack_status * %d\n", (int)*num_vals); /* check to see if there's enough data in buffer */ if (pmix_bfrop_too_small(buffer, (*num_vals)*(sizeof(pmix_status_t)))) { return PMIX_ERR_UNPACK_READ_PAST_END_OF_BUFFER; } /* unpack the data */ return pmix_bfrop_unpack_int32(buffer, dest, num_vals, PMIX_INT32); }
pmix_status_t pmix_bfrop_unpack_query(pmix_buffer_t *buffer, void *dest, int32_t *num_vals, pmix_data_type_t type) { pmix_query_t *ptr; int32_t i, n, m; pmix_status_t ret; int32_t nkeys; pmix_output_verbose(20, pmix_globals.debug_output, "pmix_bfrop_unpack: %d queries", *num_vals); ptr = (pmix_query_t *) dest; n = *num_vals; for (i = 0; i < n; ++i) { PMIX_QUERY_CONSTRUCT(&ptr[i]); /* unpack the number of keys */ m=1; if (PMIX_SUCCESS != (ret = pmix_bfrop_unpack_int32(buffer, &nkeys, &m, PMIX_INT32))) { return ret; } if (0 < nkeys) { /* unpack the keys */ if (NULL == (ptr[i].keys = (char**)calloc(nkeys+1, sizeof(char*)))) { return PMIX_ERR_NOMEM; } /* unpack keys */ m=nkeys; if (PMIX_SUCCESS != (ret = pmix_bfrop_unpack_string(buffer, ptr[i].keys, &m, PMIX_STRING))) { return ret; } } /* unpack the number of qualifiers */ m=1; if (PMIX_SUCCESS != (ret = pmix_bfrop_unpack_sizet(buffer, &ptr[i].nqual, &m, PMIX_SIZE))) { return ret; } if (0 < ptr[i].nqual) { /* unpack the qualifiers */ PMIX_INFO_CREATE(ptr[i].qualifiers, ptr[i].nqual); m = ptr[i].nqual; if (PMIX_SUCCESS != (ret = pmix_bfrop_unpack_info(buffer, ptr[i].qualifiers, &m, PMIX_INFO))) { return ret; } } } return PMIX_SUCCESS; }
pmix_status_t pmix_bfrop_unpack_app(pmix_buffer_t *buffer, void *dest, int32_t *num_vals, pmix_data_type_t type) { pmix_app_t *ptr; int32_t i, k, n, m; pmix_status_t ret; int32_t nval; char *tmp; pmix_output_verbose(20, pmix_globals.debug_output, "pmix_bfrop_unpack: %d apps", *num_vals); ptr = (pmix_app_t *) dest; n = *num_vals; for (i = 0; i < n; ++i) { /* initialize the fields */ PMIX_APP_CONSTRUCT(&ptr[i]); /* unpack cmd */ m=1; if (PMIX_SUCCESS != (ret = pmix_bfrop_unpack_string(buffer, &ptr[i].cmd, &m, PMIX_STRING))) { return ret; } /* unpack argc */ m=1; if (PMIX_SUCCESS != (ret = pmix_bfrop_unpack_int(buffer, &nval, &m, PMIX_INT32))) { return ret; } /* unpack argv */ for (k=0; k < nval; k++) { m=1; tmp = NULL; if (PMIX_SUCCESS != (ret = pmix_bfrop_unpack_string(buffer, &tmp, &m, PMIX_STRING))) { return ret; } if (NULL == tmp) { return PMIX_ERROR; } pmix_argv_append_nosize(&ptr[i].argv, tmp); free(tmp); } /* unpack env */ m=1; if (PMIX_SUCCESS != (ret = pmix_bfrop_unpack_int32(buffer, &nval, &m, PMIX_INT32))) { return ret; } for (k=0; k < nval; k++) { m=1; tmp = NULL; if (PMIX_SUCCESS != (ret = pmix_bfrop_unpack_string(buffer, &tmp, &m, PMIX_STRING))) { return ret; } if (NULL == tmp) { return PMIX_ERROR; } pmix_argv_append_nosize(&ptr[i].env, tmp); free(tmp); } /* unpack cwd */ m=1; if (PMIX_SUCCESS != (ret = pmix_bfrop_unpack_string(buffer, &ptr[i].cwd, &m, PMIX_STRING))) { return ret; } /* unpack maxprocs */ m=1; if (PMIX_SUCCESS != (ret = pmix_bfrop_unpack_int(buffer, &ptr[i].maxprocs, &m, PMIX_INT))) { return ret; } /* unpack info array */ m=1; if (PMIX_SUCCESS != (ret = pmix_bfrop_unpack_sizet(buffer, &ptr[i].ninfo, &m, PMIX_SIZE))) { return ret; } if (0 < ptr[i].ninfo) { PMIX_INFO_CREATE(ptr[i].info, ptr[i].ninfo); m = ptr[i].ninfo; if (PMIX_SUCCESS != (ret = pmix_bfrop_unpack_info(buffer, ptr[i].info, &m, PMIX_INFO))) { return ret; } } } return PMIX_SUCCESS; }
pmix_status_t pmix_bfrop_unpack(pmix_buffer_t *buffer, void *dst, int32_t *num_vals, pmix_data_type_t type) { pmix_status_t rc, ret; int32_t local_num, n=1; pmix_data_type_t local_type; /* check for error */ if (NULL == buffer || NULL == dst || NULL == num_vals) { return PMIX_ERR_BAD_PARAM; } /* if user provides a zero for num_vals, then there is no storage allocated * so return an appropriate error */ if (0 == *num_vals) { pmix_output_verbose(20, pmix_globals.debug_output, "pmix_bfrop_unpack: inadequate space ( %p, %p, %lu, %d )\n", (void*)buffer, dst, (long unsigned int)*num_vals, (int)type); return PMIX_ERR_UNPACK_INADEQUATE_SPACE; } /** Unpack the declared number of values * REMINDER: it is possible that the buffer is corrupted and that * the BFROP will *think* there is a proper int32_t variable at the * beginning of the unpack region - but that the value is bogus (e.g., just * a byte field in a string array that so happens to have a value that * matches the int32_t data type flag). Therefore, this error check is * NOT completely safe. This is true for ALL unpack functions, not just * int32_t as used here. */ if (PMIX_BFROP_BUFFER_FULLY_DESC == buffer->type) { if (PMIX_SUCCESS != (rc = pmix_bfrop_get_data_type(buffer, &local_type))) { *num_vals = 0; /* don't error log here as the user may be unpacking past * the end of the buffer, which isn't necessarily an error */ return rc; } if (PMIX_INT32 != local_type) { /* if the length wasn't first, then error */ *num_vals = 0; return PMIX_ERR_UNPACK_FAILURE; } } n=1; if (PMIX_SUCCESS != (rc = pmix_bfrop_unpack_int32(buffer, &local_num, &n, PMIX_INT32))) { *num_vals = 0; /* don't error log here as the user may be unpacking past * the end of the buffer, which isn't necessarily an error */ return rc; } pmix_output_verbose(20, pmix_globals.debug_output, "pmix_bfrop_unpack: found %d values for %d provided storage", local_num, *num_vals); /** if the storage provided is inadequate, set things up * to unpack as much as we can and to return an error code * indicating that everything was not unpacked - the buffer * is left in a state where it can not be further unpacked. */ if (local_num > *num_vals) { local_num = *num_vals; pmix_output_verbose(20, pmix_globals.debug_output, "pmix_bfrop_unpack: inadequate space ( %p, %p, %lu, %d )\n", (void*)buffer, dst, (long unsigned int)*num_vals, (int)type); ret = PMIX_ERR_UNPACK_INADEQUATE_SPACE; } else { /** enough or more than enough storage */ *num_vals = local_num; /** let the user know how many we actually unpacked */ ret = PMIX_SUCCESS; } /** Unpack the value(s) */ if (PMIX_SUCCESS != (rc = pmix_bfrop_unpack_buffer(buffer, dst, &local_num, type))) { *num_vals = 0; ret = rc; } return ret; }
pmix_status_t pmix_bfrop_unpack_rank(pmix_buffer_t *buffer, void *dest, int32_t *num_vals, pmix_data_type_t type) { return pmix_bfrop_unpack_int32(buffer, dest, num_vals, PMIX_UINT32); }
int pmix_bfrop_unpack_datatype(pmix_buffer_t *buffer, void *dest, int32_t *num_vals, pmix_data_type_t type) { return pmix_bfrop_unpack_int32(buffer, dest, num_vals, type); }