ipmi_config_err_t ipmi_config_checkout_section (ipmi_config_state_data_t *state_data, struct ipmi_config_section *section, int all_keys_if_none_specified, FILE *fp) { struct ipmi_config_keyvalue *kv; ipmi_config_err_t rv = IPMI_CONFIG_ERR_FATAL_ERROR; ipmi_config_err_t ret = IPMI_CONFIG_ERR_SUCCESS; ipmi_config_err_t this_ret; unsigned int line_length; assert (state_data); assert (section); assert (fp); /* if no keyvalues specified by user, we want to checkout all keys, * so build keyvalues list appropriately */ if (all_keys_if_none_specified && !section->keyvalues) { struct ipmi_config_key *k; k = section->keys; while (k) { if (!(k->flags & IPMI_CONFIG_DO_NOT_CHECKOUT)) { if (ipmi_config_section_add_keyvalue (state_data, section, k, NULL, NULL) < 0) goto cleanup; } k = k->next; } } if (!section->keyvalues) return (IPMI_CONFIG_ERR_SUCCESS); /* no need to output if fp NULL, for example if 'diff' is calling * us. */ if (section->section_comment_section_name && section->section_comment && all_keys_if_none_specified) { if (ipmi_config_section_comments (state_data, section->section_comment_section_name, section->section_comment, fp) < 0) { if (state_data->prog_data->args->common_args.debug) pstdout_fprintf (state_data->pstate, stderr, "## Error: Comment output error\n"); ret = IPMI_CONFIG_ERR_NON_FATAL_ERROR; } } if (!section->line_length) line_length = IPMI_CONFIG_CHECKOUT_LINE_LEN; else line_length = section->line_length; ipmi_config_pstdout_fprintf (state_data, fp, "Section %s\n", section->section_name); kv = section->keyvalues; while (kv) { int key_len = 0; if (kv->key->flags & IPMI_CONFIG_UNDEFINED) { if (ipmi_config_section_update_keyvalue_output (state_data, kv, "Undefined") < 0) this_ret = IPMI_CONFIG_ERR_FATAL_ERROR; else this_ret = IPMI_CONFIG_ERR_SUCCESS; } else { if ((this_ret = kv->key->checkout (state_data, section->section_name, kv)) == IPMI_CONFIG_ERR_FATAL_ERROR) goto cleanup; } if (IPMI_CONFIG_IS_NON_FATAL_ERROR (this_ret)) { if (state_data->prog_data->args->verbose_count > 1) { if (this_ret == IPMI_CONFIG_ERR_NON_FATAL_ERROR_NOT_SUPPORTED) ipmi_config_pstdout_fprintf (state_data, fp, "\t## Unable to checkout %s:%s : Not Supported\n", section->section_name, kv->key->key_name); else ipmi_config_pstdout_fprintf (state_data, fp, "\t## Unable to checkout %s:%s\n", section->section_name, kv->key->key_name); } ret = IPMI_CONFIG_ERR_NON_FATAL_ERROR; } else { char obuf[IPMI_CONFIG_OUTPUT_BUFLEN]; assert (kv->value_output); if (strchr (kv->key->description, '\n')) { char *cptr; cptr = kv->key->description; ipmi_config_pstdout_fprintf (state_data, fp, "\t## "); while (*cptr) { if (*cptr == '\n') ipmi_config_pstdout_fprintf (state_data, fp, "\n\t## "); else ipmi_config_pstdout_fprintf (state_data, fp, "%c", *cptr); cptr++; } ipmi_config_pstdout_fprintf (state_data, fp, "\n"); } else ipmi_config_pstdout_fprintf (state_data, fp, "\t## %s\n", kv->key->description); /* achu: Certain keys should have their checked out * value automatically commented out. Sometimes (in the * case of passwords) they cannot be checked out, so the * default is for value to be empty. We do not want the * user accidently commiting this checked out file, * which (in this example) clears the password. * * Some other keys may or may not have a value, depending on * the IPMI version or the implementation. */ /* achu: * * The pstdout library does not return string lengths like * printf/fprintf do. So we have to calculate it via * snprintf. */ if (kv->key->flags & IPMI_CONFIG_CHECKOUT_KEY_COMMENTED_OUT || kv->key->flags & IPMI_CONFIG_UNDEFINED || (kv->key->flags & IPMI_CONFIG_CHECKOUT_KEY_COMMENTED_OUT_IF_VALUE_EMPTY && !strlen (kv->value_output)) || (kv->key->flags & IPMI_CONFIG_USERNAME_NOT_SET_YET && !strcasecmp (kv->value_output, IPMI_CONFIG_USERNAME_NOT_SET_YET_STR))) key_len = snprintf (obuf, IPMI_CONFIG_OUTPUT_BUFLEN, "\t## %s", kv->key->key_name); else key_len = snprintf (obuf, IPMI_CONFIG_OUTPUT_BUFLEN, "\t%s", kv->key->key_name); ipmi_config_pstdout_fprintf (state_data, fp, "%s", obuf); while (key_len <= line_length) { ipmi_config_pstdout_fprintf (state_data, fp, " "); key_len++; } ipmi_config_pstdout_fprintf (state_data, fp, " %s\n", kv->value_output); } kv = kv->next; } ipmi_config_pstdout_fprintf (state_data, fp, "EndSection\n"); rv = ret; cleanup: return (rv); }
static ipmi_config_err_t _ipmi_config_commit_section (ipmi_config_state_data_t *state_data, struct ipmi_config_section *section) { struct ipmi_config_keyvalue *kv; ipmi_config_err_t rv = IPMI_CONFIG_ERR_FATAL_ERROR; ipmi_config_err_t ret = IPMI_CONFIG_ERR_SUCCESS; ipmi_config_err_t this_ret; unsigned int commit_count = 0; assert (state_data); assert (section); if (section->section_pre_commit) { if ((this_ret = section->section_pre_commit (state_data, section->section_name)) == IPMI_CONFIG_ERR_FATAL_ERROR) goto cleanup; if (IPMI_CONFIG_IS_NON_FATAL_ERROR (this_ret)) { pstdout_fprintf (state_data->pstate, stderr, "ERROR: Section pre-commit `%s'\n", section->section_name); ret = IPMI_CONFIG_ERR_NON_FATAL_ERROR; } } kv = section->keyvalues; while (kv) { assert (kv->value_input); if (!(kv->key->flags & IPMI_CONFIG_READABLE_ONLY) && !(kv->key->flags & IPMI_CONFIG_UNDEFINED)) { if ((this_ret = kv->key->commit (state_data, section->section_name, kv)) == IPMI_CONFIG_ERR_FATAL_ERROR) goto cleanup; if (this_ret == IPMI_CONFIG_ERR_SUCCESS) { /* Discovered on Quanta S99Q/Dell FS12-TY * * A number of values on this motherboard appear to take * a reasonable amount of time to store, causing the BMC * to return BUSY errors for a bit. In some cases, the * BMC eventually hangs or subsequent writes are * ignored. We want to try to avoid this. */ if (state_data->prog_data->args->common_args.section_specific_workaround_flags & IPMI_PARSE_SECTION_SPECIFIC_WORKAROUND_FLAGS_VERY_SLOW_COMMIT) sleep (1); commit_count++; } if (IPMI_CONFIG_IS_NON_FATAL_ERROR (this_ret)) { if (this_ret == IPMI_CONFIG_ERR_NON_FATAL_ERROR_READ_ONLY) pstdout_fprintf (state_data->pstate, stderr, "ERROR: Failed to commit `%s:%s': Read Only Field\n", section->section_name, kv->key->key_name); else if (this_ret == IPMI_CONFIG_ERR_NON_FATAL_ERROR_NOT_SUPPORTED) pstdout_fprintf (state_data->pstate, stderr, "ERROR: Failed to commit `%s:%s': Not Supported\n", section->section_name, kv->key->key_name); else if (this_ret == IPMI_CONFIG_ERR_NON_FATAL_ERROR_INVALID_UNSUPPORTED_CONFIG) pstdout_fprintf (state_data->pstate, stderr, "ERROR: Failed to commit `%s:%s': Invalid/Unsupported Config\n", section->section_name, kv->key->key_name); else pstdout_fprintf (state_data->pstate, stderr, "ERROR: Failed to commit `%s:%s'\n", section->section_name, kv->key->key_name); ret = IPMI_CONFIG_ERR_NON_FATAL_ERROR; } } else { pstdout_fprintf (state_data->pstate, stderr, "ERROR: `%s:%s' is not writeable\n", section->section_name, kv->key->key_name); ret = IPMI_CONFIG_ERR_NON_FATAL_ERROR; } kv = kv->next; } if (commit_count && section->section_post_commit) { if ((this_ret = section->section_post_commit (state_data, section->section_name)) == IPMI_CONFIG_ERR_FATAL_ERROR) goto cleanup; if (IPMI_CONFIG_IS_NON_FATAL_ERROR (this_ret)) { pstdout_fprintf (state_data->pstate, stderr, "ERROR: Section post-commit `%s'\n", section->section_name); ret = IPMI_CONFIG_ERR_NON_FATAL_ERROR; } } rv = ret; cleanup: return (rv); }