/* * Copyright (c) 2020 Red Hat, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. * * $Id: //eng/uds-releases/jasper/src/uds/indexConfig.c#2 $ */ #include "indexConfig.h" #include "buffer.h" #include "logger.h" #include "memoryAlloc.h" static const byte INDEX_CONFIG_MAGIC[] = "ALBIC"; static const byte INDEX_CONFIG_VERSION[] = "06.02"; static const byte INDEX_CONFIG_VERSION_6_01[] = "06.01"; enum { INDEX_CONFIG_MAGIC_LENGTH = sizeof(INDEX_CONFIG_MAGIC) - 1, INDEX_CONFIG_VERSION_LENGTH = sizeof(INDEX_CONFIG_VERSION) - 1 }; /**********************************************************************/ __attribute__((warn_unused_result)) static int decodeIndexConfig(Buffer *buffer, UdsConfiguration config) { int result = getUInt32LEFromBuffer(buffer, &config->recordPagesPerChapter); if (result != UDS_SUCCESS) { return result; } result = getUInt32LEFromBuffer(buffer, &config->chaptersPerVolume); if (result != UDS_SUCCESS) { return result; } result = getUInt32LEFromBuffer(buffer, &config->sparseChaptersPerVolume); if (result != UDS_SUCCESS) { return result; } result = getUInt32LEFromBuffer(buffer, &config->cacheChapters); if (result != UDS_SUCCESS) { return result; } result = getUInt32LEFromBuffer(buffer, &config->checkpointFrequency); if (result != UDS_SUCCESS) { return result; } result = getUInt32LEFromBuffer(buffer, &config->masterIndexMeanDelta); if (result != UDS_SUCCESS) { return result; } result = getUInt32LEFromBuffer(buffer, &config->bytesPerPage); if (result != UDS_SUCCESS) { return result; } result = getUInt32LEFromBuffer(buffer, &config->sparseSampleRate); if (result != UDS_SUCCESS) { return result; } result = getUInt64LEFromBuffer(buffer, &config->nonce); if (result != UDS_SUCCESS) { return result; } result = ASSERT_LOG_ONLY(contentLength(buffer) == 0, "%zu bytes decoded of %zu expected", bufferLength(buffer) - contentLength(buffer), bufferLength(buffer)); if (result != UDS_SUCCESS) { result = UDS_CORRUPT_COMPONENT; } return result; } /**********************************************************************/ static int readVersion(BufferedReader *reader, UdsConfiguration conf, const char **versionPtr) { byte buffer[INDEX_CONFIG_VERSION_LENGTH]; int result = readFromBufferedReader(reader, buffer, INDEX_CONFIG_VERSION_LENGTH); if (result != UDS_SUCCESS) { return logErrorWithStringError(result, "cannot read index config version"); } if (memcmp(INDEX_CONFIG_VERSION, buffer, INDEX_CONFIG_VERSION_LENGTH) == 0) { Buffer *buffer; result = makeBuffer(sizeof(*conf), &buffer); if (result != UDS_SUCCESS) { return result; } result = readFromBufferedReader(reader, getBufferContents(buffer), bufferLength(buffer)); if (result != UDS_SUCCESS) { freeBuffer(&buffer); return logErrorWithStringError(result, "cannot read config data"); } clearBuffer(buffer); result = decodeIndexConfig(buffer, conf); freeBuffer(&buffer); if (result != UDS_SUCCESS) { return result; } if (versionPtr != NULL) { *versionPtr = "current"; } return result; } else if (memcmp(INDEX_CONFIG_VERSION_6_01, buffer, INDEX_CONFIG_VERSION_LENGTH) == 0) { struct udsConfiguration6_01 oldConf; result = readFromBufferedReader(reader, &oldConf, sizeof(oldConf)); if (result != UDS_SUCCESS) { logErrorWithStringError(result, "failed to read version 6.01 config file"); return result; } conf->recordPagesPerChapter = oldConf.recordPagesPerChapter; conf->chaptersPerVolume = oldConf.chaptersPerVolume; conf->sparseChaptersPerVolume = oldConf.sparseChaptersPerVolume; conf->cacheChapters = oldConf.cacheChapters; conf->checkpointFrequency = oldConf.checkpointFrequency; conf->masterIndexMeanDelta = oldConf.masterIndexMeanDelta; conf->bytesPerPage = oldConf.bytesPerPage; conf->sparseSampleRate = oldConf.sparseSampleRate; conf->nonce = 0; if (versionPtr != NULL) { *versionPtr = "6.01"; } return UDS_UNSUPPORTED_VERSION; } return logErrorWithStringError(UDS_CORRUPT_COMPONENT, "unsupported configuration version: '%.*s'", INDEX_CONFIG_VERSION_LENGTH, buffer); } /**********************************************************************/ int readConfigContents(BufferedReader *reader, UdsConfiguration config) { int result = verifyBufferedData(reader, INDEX_CONFIG_MAGIC, INDEX_CONFIG_MAGIC_LENGTH); if (result != UDS_SUCCESS) { return result; } const char *version = NULL; result = readVersion(reader, config, &version); if (result != UDS_SUCCESS) { if (result == UDS_UNSUPPORTED_VERSION) { logNoticeWithStringError(result, "Found index config version %s", version); } else { logErrorWithStringError(result, "Failed to read index config"); } } return result; } /**********************************************************************/ __attribute__((warn_unused_result)) static int encodeIndexConfig(Buffer *buffer, UdsConfiguration config) { int result = putUInt32LEIntoBuffer(buffer, config->recordPagesPerChapter); if (result != UDS_SUCCESS) { return result; } result = putUInt32LEIntoBuffer(buffer, config->chaptersPerVolume); if (result != UDS_SUCCESS) { return result; } result = putUInt32LEIntoBuffer(buffer, config->sparseChaptersPerVolume); if (result != UDS_SUCCESS) { return result; } result = putUInt32LEIntoBuffer(buffer, config->cacheChapters); if (result != UDS_SUCCESS) { return result; } result = putUInt32LEIntoBuffer(buffer, config-> checkpointFrequency); if (result != UDS_SUCCESS) { return result; } result = putUInt32LEIntoBuffer(buffer, config->masterIndexMeanDelta); if (result != UDS_SUCCESS) { return result; } result = putUInt32LEIntoBuffer(buffer, config->bytesPerPage); if (result != UDS_SUCCESS) { return result; } result = putUInt32LEIntoBuffer(buffer, config->sparseSampleRate); if (result != UDS_SUCCESS) { return result; } result = putUInt64LEIntoBuffer(buffer, config->nonce); if (result != UDS_SUCCESS) { return result; } result = ASSERT_LOG_ONLY(contentLength(buffer) == sizeof(*config), "%zu bytes encoded, of %zu expected", contentLength(buffer), sizeof(*config)); return result; } /**********************************************************************/ int writeConfigContents(BufferedWriter *writer, UdsConfiguration config) { int result = writeToBufferedWriter(writer, INDEX_CONFIG_MAGIC, INDEX_CONFIG_MAGIC_LENGTH); if (result != UDS_SUCCESS) { return result; } result = writeToBufferedWriter(writer, INDEX_CONFIG_VERSION, INDEX_CONFIG_VERSION_LENGTH); if (result != UDS_SUCCESS) { return result; } Buffer *buffer; result = makeBuffer(sizeof(*config), &buffer); if (result != UDS_SUCCESS) { return result; } result = encodeIndexConfig(buffer, config); if (result != UDS_SUCCESS) { freeBuffer(&buffer); return result; } result = writeToBufferedWriter(writer, getBufferContents(buffer), contentLength(buffer)); freeBuffer(&buffer); return result; } /**********************************************************************/ int makeConfiguration(UdsConfiguration conf, Configuration **configPtr) { *configPtr = NULL; if (conf == NULL) { return logErrorWithStringError(UDS_CONF_REQUIRED, "received an invalid config"); } Configuration *config; int result = ALLOCATE(1, Configuration, "configuration", &config); if (result != UDS_SUCCESS) { return result; } result = makeGeometry(conf->bytesPerPage, conf->recordPagesPerChapter, conf->chaptersPerVolume, conf->sparseChaptersPerVolume, &config->geometry); if (result != UDS_SUCCESS) { freeConfiguration(config); return result; } config->sparseSampleRate = conf->sparseSampleRate; config->cacheChapters = conf->cacheChapters; config->masterIndexMeanDelta = conf->masterIndexMeanDelta; *configPtr = config; return UDS_SUCCESS; } /**********************************************************************/ void freeConfiguration(Configuration *config) { if (config != NULL) { freeGeometry(config->geometry); FREE(config); } }