/* Add DSP Entry */ static eEsifError esif_dsp_entry_create(struct esif_ccb_file *file_ptr) { eEsifError rc = ESIF_E_UNSPECIFIED; EsifDspPtr dspPtr = NULL; EsifFpcPtr fpcPtr = NULL; UInt32 fpcIsStatic = ESIF_FALSE; UInt8 i = 0; char path[MAX_PATH]={0}; UInt32 fpcSize = 0; UInt32 edpSize = 0; size_t numFpcBytesRead = 0; struct edp_dir edp_dir; EsifDataPtr nameSpace = 0; EsifDataPtr key = 0; EsifDataPtr value = 0; IOStreamPtr ioPtr = IOStream_Create(); if ((NULL == file_ptr) || (NULL == ioPtr)) { ESIF_TRACE_ERROR("The file pointer or IO stream is NULL\n"); goto exit; } nameSpace = EsifData_CreateAs(ESIF_DATA_STRING, ESIF_DSP_NAMESPACE, 0, ESIFAUTOLEN); key = EsifData_CreateAs(ESIF_DATA_STRING, file_ptr->filename, 0, ESIFAUTOLEN); value = EsifData_CreateAs(ESIF_DATA_AUTO, NULL, ESIF_DATA_ALLOCATE, 0); if (nameSpace == NULL || key == NULL || value == NULL) { rc = ESIF_E_NO_MEMORY; goto exit; } ESIF_TRACE_DEBUG("Filename: %s", file_ptr->filename); dspPtr = esif_dsp_create(); if (NULL == dspPtr) { ESIF_TRACE_ERROR("Fail to allocate dsp entry\n"); goto exit; } // Look for EDP file on disk first then in DataVault (static or file) esif_build_path(path, sizeof(path), ESIF_PATHTYPE_DSP, file_ptr->filename, NULL); if (!esif_ccb_file_exists(path) && EsifConfigGet(nameSpace, key, value) == ESIF_OK) { esif_ccb_strcpy(path, file_ptr->filename, MAX_PATH); IOStream_SetMemory(ioPtr, StoreReadOnly, (BytePtr)value->buf_ptr, value->data_len); } else { IOStream_SetFile(ioPtr, StoreReadOnly, path, "rb"); } ESIF_TRACE_DEBUG("Fullpath: %s", path); if (IOStream_Open(ioPtr) != 0) { ESIF_TRACE_ERROR("File not found (%s)", path); goto exit; } /* Read FPC From EDP File */ if (esif_ccb_strstr(&path[0], ".edp")) { /* EDP - Only Read The FPC Part */ edpSize = (UInt32)IOStream_GetSize(ioPtr); if (!edpSize) { goto exit; } numFpcBytesRead = IOStream_Read(ioPtr, &edp_dir, sizeof(edp_dir)); if (!esif_verify_edp(&edp_dir, numFpcBytesRead)) { ESIF_TRACE_ERROR("Invalid EDP Header: Signature=%4.4s Version=%d\n", (char *)&edp_dir.signature, edp_dir.version); goto exit; } if (edpSize > MAX_EDP_SIZE || edp_dir.fpc_offset > MAX_FPC_SIZE || edp_dir.fpc_offset > edpSize) { ESIF_TRACE_ERROR("The edp or fpc file size is larger than maximum\n"); goto exit; } fpcSize = edpSize - edp_dir.fpc_offset; IOStream_Seek(ioPtr, edp_dir.fpc_offset, SEEK_SET); ESIF_TRACE_DEBUG("File found (%s) size %u, FPC size %u from offset %u", path, edpSize, fpcSize, edp_dir.fpc_offset); } else { ESIF_TRACE_DEBUG("File %s does not have .fpc and .edp format!", path); } // use static DataVault buffer (if available), otherwise allocate space for our FPC file contents (which will not be freed) if (IOStream_GetType(ioPtr) == StreamMemory && value->buf_len == 0) { fpcPtr = (EsifFpcPtr)IOStream_GetMemoryBuffer(ioPtr); if (NULL == fpcPtr) { ESIF_TRACE_ERROR("NULL buffer"); goto exit; } fpcPtr = (EsifFpcPtr) (((BytePtr) fpcPtr) + IOStream_GetOffset(ioPtr)); numFpcBytesRead = fpcSize; ESIF_TRACE_DEBUG("Static vault size %u buf_ptr=0x%p\n", (int)numFpcBytesRead, fpcPtr); fpcIsStatic = ESIF_TRUE; } else { fpcPtr = (EsifFpcPtr)esif_ccb_malloc(fpcSize); if (NULL == fpcPtr) { ESIF_TRACE_ERROR("malloc failed to allocate %u bytes\n", fpcSize); goto exit; } ESIF_TRACE_DEBUG("File malloc size %u", fpcSize); // read file contents numFpcBytesRead = IOStream_Read(ioPtr, fpcPtr, fpcSize); if (numFpcBytesRead < fpcSize) { ESIF_TRACE_ERROR("Read short received %u of %u bytes\n", (int)numFpcBytesRead, fpcSize); goto exit; } ESIF_TRACE_DEBUG("File read size %u", (int)numFpcBytesRead); } ESIF_TRACE_DEBUG("\nDecode Length: %u", fpcPtr->size); ESIF_TRACE_DEBUG("Code: %s", fpcPtr->header.code); ESIF_TRACE_DEBUG("Ver Major: %u", fpcPtr->header.ver_major); ESIF_TRACE_DEBUG("Ver Minor: %u", fpcPtr->header.ver_minor); ESIF_TRACE_DEBUG("Name: %s", fpcPtr->header.name); ESIF_TRACE_DEBUG("Description: %s", fpcPtr->header.description); ESIF_TRACE_DEBUG("Type: %s", fpcPtr->header.type); ESIF_TRACE_DEBUG("Bus Enumerator: %u", fpcPtr->header.bus_enum); ESIF_TRACE_DEBUG("ACPI Device: %s", fpcPtr->header.acpi_device); ESIF_TRACE_DEBUG("ACPI Scope: %s", fpcPtr->header.acpi_scope); ESIF_TRACE_DEBUG("ACPI Type: %s", fpcPtr->header.acpi_type); ESIF_TRACE_DEBUG("ACPI UID: %s", fpcPtr->header.acpi_UID); ESIF_TRACE_DEBUG("PCI Vendor ID: %s", fpcPtr->header.pci_vendor_id); ESIF_TRACE_DEBUG("PCI Device ID: %s", fpcPtr->header.pci_device_id); ESIF_TRACE_DEBUG("PCI Bus: %s", fpcPtr->header.pci_bus); ESIF_TRACE_DEBUG("PCI Device: %s", fpcPtr->header.pci_device); ESIF_TRACE_DEBUG("PCI Function: %s", fpcPtr->header.pci_function); dspPtr->code_ptr = (EsifString)fpcPtr->header.name; dspPtr->bus_enum = (UInt8 *)&fpcPtr->header.bus_enum; dspPtr->type = (EsifString)fpcPtr->header.type; dspPtr->ver_major_ptr = (UInt8 *)&fpcPtr->header.ver_major; dspPtr->ver_minor_ptr = (UInt8 *)&fpcPtr->header.ver_minor; dspPtr->acpi_device = (EsifString)fpcPtr->header.acpi_device; dspPtr->acpi_scope = (EsifString)fpcPtr->header.acpi_scope; dspPtr->acpi_type = (EsifString)fpcPtr->header.acpi_type; dspPtr->acpi_uid = (EsifString)fpcPtr->header.acpi_UID; dspPtr->vendor_id = (EsifString)fpcPtr->header.pci_vendor_id; dspPtr->device_id = (EsifString)fpcPtr->header.pci_device_id; dspPtr->pci_bus = (EsifString)&fpcPtr->header.pci_bus; dspPtr->pci_bus_device = (EsifString)&fpcPtr->header.pci_device; dspPtr->pci_function = (EsifString)&fpcPtr->header.pci_function; /* Assign Function Pointers */ dspPtr->get_code = get_code; dspPtr->get_ver_minor = get_ver_minor; dspPtr->get_ver_major = get_ver_major; dspPtr->get_temp_tc1 = get_temp_c1; dspPtr->get_percent_xform = get_percent_xform; dspPtr->insert_primitive = insert_primitive; dspPtr->insert_algorithm = insert_algorithm; dspPtr->insert_domain = insert_domain; dspPtr->insert_event = insert_event; dspPtr->get_primitive = get_primitive; dspPtr->get_action = get_action; dspPtr->get_algorithm = get_algorithm; dspPtr->get_domain = get_domain; dspPtr->get_event_by_type = get_event_by_type; dspPtr->get_event_by_guid = get_event_by_guid; dspPtr->init_fpc_iterator = init_fpc_iterator; dspPtr->get_next_fpc_domain = get_next_fpc_domain; dspPtr->get_domain_count = get_domain_count; rc = esif_fpc_load(fpcPtr, dspPtr); if (ESIF_OK == rc) { ESIF_TRACE_DEBUG("FPC %s load successfully", path); } else { ESIF_TRACE_DEBUG("Unable to load FPC %s, rc %s", path, esif_rc_str(rc)); goto exit; } /* Lock DSP Manager */ esif_ccb_write_lock(&g_dm.lock); /* Simple Table Lookup For Now. Scan Table And Find First Empty Slot */ /* Empty slot indicated by AVAILABLE state */ for (i = 0; i < MAX_DSP_MANAGER_ENTRY; i++) { if (NULL == g_dm.dme[i].dsp_ptr) { break; } } /* If No Available Slots Return */ if (i >= MAX_DSP_MANAGER_ENTRY) { esif_ccb_write_unlock(&g_dm.lock); ESIF_TRACE_ERROR("No free dsp manager entry is available for %s\n", file_ptr->filename); goto exit; } /* ** Take Slot */ g_dm.dme[i].dsp_ptr = dspPtr; g_dm.dme[i].file_ptr = file_ptr; g_dm.dme[i].fpc_ptr = (fpcIsStatic ? 0 : fpcPtr); g_dm.dme_count++; dspPtr = NULL; // Prevent deallocate on exit fpcPtr = NULL; // Prevent deallocate on exit esif_ccb_write_unlock(&g_dm.lock); rc = ESIF_OK; ESIF_TRACE_INFO("Create entry in dsp manager successfully for %s\n", file_ptr->filename); exit: IOStream_Destroy(ioPtr); EsifData_Destroy(nameSpace); EsifData_Destroy(key); EsifData_Destroy(value); esif_dsp_destroy(dspPtr); if (!fpcIsStatic) { esif_ccb_free(fpcPtr); } return rc; }
// Reads a key/value pair from the current location in the open DataVault stream static eEsifError DataVault_ReadNextKeyValuePair( DataVaultPtr self, esif_flags_t *flagsPtr, EsifDataPtr keyPtr, EsifDataPtr valuePtr ) { eEsifError rc = ESIF_OK; IOStreamPtr vault = NULL; size_t bytes = 0; ESIF_ASSERT(self != NULL); ESIF_ASSERT(flagsPtr != NULL); ESIF_ASSERT(keyPtr != NULL); ESIF_ASSERT(valuePtr != NULL); vault = self->stream; // Read Flags if ((bytes = IOStream_Read(vault, flagsPtr, sizeof(*flagsPtr))) != sizeof(*flagsPtr)) { // Check if we are done if (bytes != 0) { rc = ESIF_E_IO_ERROR; } rc = ESIF_E_ITERATION_DONE; goto exit; } // Read key length keyPtr->type = ESIF_DATA_STRING; if (IOStream_Read(vault, &keyPtr->data_len, sizeof(keyPtr->data_len)) < sizeof(keyPtr->data_len)) { rc = ESIF_E_IO_ERROR; goto exit; } if (keyPtr->data_len > MAX_DV_DATALEN) { rc = ESIF_E_PARAMETER_IS_OUT_OF_BOUNDS; goto exit; } // Use Memory Pointers for Static DataVaults, otherwise allocate memory if ((IOStream_GetType(vault) == StreamMemory) && (self->flags & ESIF_SERVICE_CONFIG_STATIC)) { keyPtr->buf_len = 0; keyPtr->buf_ptr = IOStream_GetMemoryBuffer(vault) + IOStream_GetOffset(vault); if (IOStream_Seek(vault, keyPtr->data_len, SEEK_CUR) != EOK) { rc = ESIF_E_IO_ERROR; goto exit; } *flagsPtr &= ~ESIF_SERVICE_CONFIG_NOCACHE; // ignore for Static DataVaults } else { keyPtr->buf_len = esif_ccb_max(1, keyPtr->data_len); keyPtr->buf_ptr = esif_ccb_malloc(keyPtr->buf_len); if (!keyPtr->buf_ptr) { rc = ESIF_E_NO_MEMORY; goto exit; } if (IOStream_Read(vault, keyPtr->buf_ptr, keyPtr->data_len) != keyPtr->data_len) { rc = ESIF_E_IO_ERROR; goto exit; } else if (keyPtr->data_len) { ((esif_string)(keyPtr->buf_ptr))[keyPtr->data_len - 1] = 0; } } // Read Value if (IOStream_Read(vault, &valuePtr->type, sizeof(valuePtr->type)) != sizeof(valuePtr->type)) { rc = ESIF_E_IO_ERROR; goto exit; } if (IOStream_Read(vault, &valuePtr->data_len, sizeof(valuePtr->data_len)) != sizeof(valuePtr->data_len)) { rc = ESIF_E_IO_ERROR; goto exit; } if (valuePtr->data_len > MAX_DV_DATALEN) { rc = ESIF_E_PARAMETER_IS_OUT_OF_BOUNDS; goto exit; } // If NOCACHE mode, use buf_ptr to store the file offset of the data and skip the file if (*flagsPtr & ESIF_SERVICE_CONFIG_NOCACHE) { size_t offset = IOStream_GetOffset(vault); if (IOStream_Seek(vault, valuePtr->data_len, SEEK_CUR) != EOK) { rc = ESIF_E_IO_ERROR; goto exit; } valuePtr->buf_ptr = (void*)offset; // For non-cached...we save the offset in the file as the buffer pointer. Really??? valuePtr->buf_len = 0; // buf_len == 0 so we don't release buffer as not allocated; data_len = original length } else { // Use static pointer for static data vaults (unless scrambled), otherwise make a dynamic copy if ((IOStream_GetType(vault) == StreamMemory) && (self->flags & ESIF_SERVICE_CONFIG_STATIC) && !(*flagsPtr & ESIF_SERVICE_CONFIG_SCRAMBLE)) { valuePtr->buf_len = 0; // static valuePtr->buf_ptr = IOStream_GetMemoryBuffer(vault) + IOStream_GetOffset(vault); if (valuePtr->buf_ptr == NULL || IOStream_Seek(vault, valuePtr->data_len, SEEK_CUR) != EOK) { rc = ESIF_E_IO_ERROR; goto exit; } } else { valuePtr->buf_len = esif_ccb_max(1, valuePtr->data_len); // dynamic valuePtr->buf_ptr = esif_ccb_malloc(valuePtr->buf_len); if (valuePtr->buf_ptr == NULL) { rc = ESIF_E_NO_MEMORY; goto exit; } else if (IOStream_Read(vault, valuePtr->buf_ptr, valuePtr->data_len) != valuePtr->data_len) { rc = ESIF_E_IO_ERROR; goto exit; } } // Unscramble Data? if (*flagsPtr & ESIF_SERVICE_CONFIG_SCRAMBLE) { UInt32 byte; for (byte = 0; byte < valuePtr->data_len; byte++) ((UInt8*)(valuePtr->buf_ptr))[byte] = ~((UInt8*)(valuePtr->buf_ptr))[byte]; } } exit: return rc; }
static eEsifError DataVault_ReadPayload(DataVaultPtr self) { eEsifError rc = ESIF_OK; IOStreamPtr streamPtr = NULL; int vrc = EPERM; size_t fileOffset = 0; size_t curFileOffset = 0; size_t pairSize = 0; esif_flags_t item_flags = 0; EsifData key = { ESIF_DATA_STRING }; EsifData value = { ESIF_DATA_VOID }; ESIF_ASSERT(self != NULL); streamPtr = self->stream; // Open File or Memory Block if ((vrc = IOStream_Open(streamPtr)) != 0) { if (vrc == ENOENT) { rc = ESIF_E_NOT_FOUND; } else { rc = ESIF_E_IO_OPEN_FAILED; } goto exit; } // Move the file pointer to start of data fileOffset = sizeof(DataVaultHeader); if (IOStream_Seek(streamPtr, fileOffset, SEEK_SET) != EOK) { rc = ESIF_E_IO_ERROR; goto exit; } // Read Data and add to DataVault while (rc == ESIF_OK) { EsifData_ctor(&key); EsifData_ctor(&value); item_flags = 0; rc = DataVault_ReadNextKeyValuePair(self, &item_flags, &key, &value); if (rc != ESIF_OK) { if (ESIF_E_ITERATION_DONE == rc) { rc = ESIF_OK; } break; } // Validate that the data read is from within the region specified by the header curFileOffset = IOStream_GetOffset(streamPtr); pairSize = curFileOffset - fileOffset; fileOffset = curFileOffset; // Add value (including allocated buf_ptr) to cache DataCache_InsertValue(self->cache, (esif_string)key.buf_ptr, &value, item_flags); EsifData_dtor(&key); EsifData_dtor(&value); } exit: IOStream_Close(streamPtr); EsifData_dtor(&key); EsifData_dtor(&value); return rc; }
static eEsifError DataVault_WriteKeyValuePair( DataVaultPtr self, DataCacheEntryPtr pairPtr, IOStreamPtr destStreamPtr ) { eEsifError rc = ESIF_OK; IOStreamPtr diskStreamPtr = NULL; UInt8 *buffer = NULL; UInt32 buffer_len = 0; UInt32 byte = 0; size_t orgOffset = 0; size_t newOffset = 0; ESIF_ASSERT(self != NULL); ESIF_ASSERT(pairPtr != NULL); ESIF_ASSERT(destStreamPtr != NULL); // Expected to be open diskStreamPtr = self->stream; // Write Flags: <flags> if (IOStream_Write(destStreamPtr, &pairPtr->flags, sizeof(pairPtr->flags)) != sizeof(pairPtr->flags)) { rc = ESIF_E_IO_ERROR; goto exit; } // Write Key: <len><value...> if (IOStream_Write(destStreamPtr, &pairPtr->key.data_len, sizeof(pairPtr->key.data_len)) != sizeof(pairPtr->key.data_len)) { rc = ESIF_E_IO_ERROR; goto exit; } if (IOStream_Write(destStreamPtr, pairPtr->key.buf_ptr, pairPtr->key.data_len) != pairPtr->key.data_len) { rc = ESIF_E_IO_ERROR; goto exit; } // Write Value: <type><len><value...> if (IOStream_Write(destStreamPtr, &pairPtr->value.type, sizeof(pairPtr->value.type)) != sizeof(pairPtr->value.type)) { rc = ESIF_E_IO_ERROR; goto exit; } if (IOStream_Write(destStreamPtr, &pairPtr->value.data_len, sizeof(pairPtr->value.data_len)) != sizeof(pairPtr->value.data_len)) { rc = ESIF_E_IO_ERROR; goto exit; } // Read NOCACHE Entries from disk file if (pairPtr->flags & ESIF_SERVICE_CONFIG_NOCACHE) { newOffset = IOStream_GetOffset(destStreamPtr); // Read Block from disk if (pairPtr->value.buf_len == 0) { orgOffset = (size_t)pairPtr->value.buf_ptr; buffer = (UInt8*)esif_ccb_malloc(pairPtr->value.data_len); buffer_len = pairPtr->value.data_len; if (!buffer) { rc = ESIF_E_NO_MEMORY; goto exit; } rc = DataVault_GetFromSource(self, buffer, buffer_len, orgOffset); if (rc != ESIF_OK) { goto exit; } } // Convert internal storage to NOCACHE else { buffer = (UInt8*)pairPtr->value.buf_ptr; buffer_len = pairPtr->value.data_len; pairPtr->value.buf_len = 0;// Set to 0 so we don't free twice } // Update pair with offset in new file pairPtr->value.buf_ptr = (void*)newOffset; } // Scramble Data? if (pairPtr->flags & ESIF_SERVICE_CONFIG_SCRAMBLE) { if (!buffer) { buffer = (UInt8*)esif_ccb_malloc(pairPtr->value.data_len); buffer_len = pairPtr->value.data_len; if (!buffer) { rc = ESIF_E_NO_MEMORY; goto exit; } } for (byte = 0; byte < pairPtr->value.data_len; byte++) buffer[byte] = ~((UInt8*)(pairPtr->value.buf_ptr))[byte]; } if (buffer) { if (IOStream_Write(destStreamPtr, buffer, buffer_len) != buffer_len) rc = ESIF_E_IO_ERROR; } else { if (IOStream_Write(destStreamPtr, pairPtr->value.buf_ptr, pairPtr->value.data_len) != pairPtr->value.data_len) rc = ESIF_E_IO_ERROR; } exit: esif_ccb_free(buffer); return rc; }
// Read DataVault from Disk eEsifError DataVault_ReadVault (DataVaultPtr self) { eEsifError rc = ESIF_E_UNSPECIFIED; // TODO int vrc = EPERM; DataVaultHeader header; UInt32 min_version; UInt32 max_version; esif_flags_t item_flags; IOStreamPtr vault = self->stream; // TODO: Locking // Open File or Memory Block if ((vrc = IOStream_Open(vault)) != 0) { if (vrc == ENOENT) { rc = ESIF_E_NOT_FOUND; } return rc; } // Read and Verify File Header // The DataVault's Major.Minor Version must be <= the App's Major.Minor Version and at least Major.0 memset(&header, 0, sizeof(header)); IOStream_Read(vault, &header, 4); // E51F#### where #### is header size, including this IOStream_Read(vault, ((UInt8*)&header) + 4, esif_ccb_min(header.headersize, sizeof(header)) - 4); min_version = ESIFDV_VERSION(ESIFDV_MAJOR_VERSION, 0, 0); max_version = ESIFDV_VERSION(ESIFDV_MAJOR_VERSION, ESIFDV_MINOR_VERSION, ESIFDV_MAX_REVISION); if (memcmp(header.signature, ESIFDV_SIGNATURE, sizeof(header.signature)) != 0 || header.version > max_version || header.version < min_version) { IOStream_Close(vault); return ESIF_E_NOT_SUPPORTED; } if (header.headersize > sizeof(header)) { IOStream_Seek(vault, header.headersize - sizeof(header), SEEK_CUR); } self->flags = header.flags; if (IOStream_GetType(vault) == StreamMemory) { self->flags |= ESIF_SERVICE_CONFIG_STATIC; } rc = ESIF_OK; // Read Data and add to DataVault while (IOStream_Read(vault, &item_flags, sizeof(item_flags)) == sizeof(item_flags)) { EsifData key; EsifData value; // Read Key EsifData_ctor(&key); EsifData_ctor(&value); key.type = ESIF_DATA_STRING; IOStream_Read(vault, &key.data_len, sizeof(key.data_len)); if (key.data_len > MAX_DV_DATALEN) { rc = ESIF_E_PARAMETER_IS_OUT_OF_BOUNDS; break; } switch (IOStream_GetType(vault)) { case StreamMemory: key.buf_len = 0; key.buf_ptr = IOStream_GetMemoryBuffer(vault) + IOStream_GetOffset(vault); IOStream_Seek(vault, key.data_len, SEEK_CUR); item_flags &= ~ESIF_SERVICE_CONFIG_NOCACHE; // ignore for Memory Vaults break; case StreamFile: default: key.buf_len = key.data_len; key.buf_ptr = esif_ccb_malloc(key.buf_len); if (!key.buf_ptr) { rc = ESIF_E_NO_MEMORY; break; } IOStream_Read(vault, key.buf_ptr, key.data_len); ((esif_string)(key.buf_ptr))[key.data_len - 1] = 0; break; } if (rc != ESIF_OK) { EsifData_dtor(&key); break; } // Read Value IOStream_Read(vault, &value.type, sizeof(value.type)); IOStream_Read(vault, &value.data_len, sizeof(value.data_len)); if (value.data_len > MAX_DV_DATALEN) { EsifData_dtor(&key); break; } // If NOCACHE mode, use buf_ptr to store the file offset of the data and skip the file if (item_flags & ESIF_SERVICE_CONFIG_NOCACHE) { size_t offset = IOStream_GetOffset(vault); IOStream_Seek(vault, value.data_len, SEEK_CUR); value.buf_ptr = (void*)offset; value.buf_len = 0; // data_len = original length } else { // Use static pointer for static data vaults (unless encrypted), otherwise make a dynamic copy if (IOStream_GetType(vault) == StreamMemory && !(item_flags & ESIF_SERVICE_CONFIG_ENCRYPT)) { value.buf_len = 0; // static value.buf_ptr = IOStream_GetMemoryBuffer(vault) + IOStream_GetOffset(vault); IOStream_Seek(vault, value.data_len, SEEK_CUR); } else { value.buf_len = value.data_len; // dynamic value.buf_ptr = esif_ccb_malloc(value.buf_len); if (!value.buf_ptr) { EsifData_dtor(&key); rc = ESIF_E_NO_MEMORY; break; } IOStream_Read(vault, value.buf_ptr, value.data_len); } // Decrypt Encrypted Data? if (item_flags & ESIF_SERVICE_CONFIG_ENCRYPT) { UInt32 byte; for (byte = 0; byte < value.data_len; byte++) ((UInt8*)(value.buf_ptr))[byte] = ~((UInt8*)(value.buf_ptr))[byte]; } } // Add value (including allocated buf_ptr) to cache DataCache_SetValue(self->cache, (esif_string)key.buf_ptr, value, item_flags); value.buf_ptr = 0; item_flags = 0; EsifData_dtor(&key); EsifData_dtor(&value); } IOStream_Close(vault); return rc; }
// Write DataVault to Disk eEsifError DataVault_WriteVault (DataVaultPtr self) { eEsifError rc = ESIF_E_NOT_FOUND; DataVaultHeader header; struct esif_ccb_file dv_file = {0}; struct esif_ccb_file dv_filebak = {0}; IOStreamPtr vault = 0; IOStreamPtr vaultBak = 0; u32 idx; if (FLAGS_TEST(self->flags, ESIF_SERVICE_CONFIG_STATIC | ESIF_SERVICE_CONFIG_READONLY)) { return ESIF_E_READONLY; } // TODO: Locking vault = IOStream_Create(); if (!vault) { return ESIF_E_NO_MEMORY; } // If any rows contain NOCACHE PERSIST values, we need to make a copy the original DataVault while creating the new one // esif_ccb_sprintf(MAX_PATH, dv_file.filename, "%s%s", esif_build_path(dv_file.filename, MAX_PATH, NULL, self->name), ESIFDV_FILEEXT); esif_ccb_sprintf(MAX_PATH, dv_file.filename, "%s%s%s", ESIFDV_DIR, self->name, ESIFDV_FILEEXT); for (idx = 0; idx < self->cache->size; idx++) if (FLAGS_TESTALL(self->cache->elements[idx].flags, ESIF_SERVICE_CONFIG_NOCACHE | ESIF_SERVICE_CONFIG_PERSIST) && self->cache->elements[idx].value.buf_len == 0) { struct stat filebak_stat = {0}; esif_ccb_sprintf(MAX_PATH, dv_filebak.filename, "%s%s%s", ESIFDV_DIR, self->name, ESIFDV_BAKFILEEXT); // Delete BAK file if it exists if (esif_ccb_stat(dv_filebak.filename, &filebak_stat) == 0) { esif_ccb_unlink(dv_filebak.filename); } if (esif_ccb_rename(dv_file.filename, dv_filebak.filename) == 0) { if ((vaultBak = IOStream_Create()) == NULL) { rc = ESIF_E_NO_MEMORY; } if (!vaultBak || IOStream_OpenFile(vaultBak, dv_filebak.filename, "rb") != 0) { IOStream_Destroy(vault); IOStream_Destroy(vaultBak); return rc; } } break; } // Create DataVault, Overwrite if necessary IOStream_SetFile(vault, self->stream->file.name, "wb"); if (IOStream_Open(vault) != 0) { if (vaultBak) { IOStream_Destroy(vaultBak); esif_ccb_unlink(dv_filebak.filename); } IOStream_Destroy(vault); return rc; } // Create File Header memset(&header, 0, sizeof(header)); esif_ccb_memcpy(&header.signature, ESIFDV_SIGNATURE, sizeof(header.signature)); header.headersize = sizeof(header); header.version = ESIFDV_VERSION(ESIFDV_MAJOR_VERSION, ESIFDV_MINOR_VERSION, ESIFDV_REVISION); header.flags = 0; // TODO: get from self->flags // Write File Header IOStream_Seek(vault, 0, SEEK_SET); IOStream_Write(vault, &header, sizeof(header)); rc = ESIF_OK; // Write All Persisted Rows from Sorted List to DataVault for (idx = 0; idx < self->cache->size; idx++) { DataCacheEntryPtr keypair = &self->cache->elements[idx]; if (keypair->flags & ESIF_SERVICE_CONFIG_PERSIST) { UInt8 *buffer = 0; UInt32 buffer_len = 0; UInt32 byte = 0; IOStream_Write(vault, &keypair->flags, sizeof(keypair->flags)); IOStream_Write(vault, &keypair->key.data_len, sizeof(keypair->key.data_len)); IOStream_Write(vault, keypair->key.buf_ptr, keypair->key.data_len); IOStream_Write(vault, &keypair->value.type, sizeof(keypair->value.type)); IOStream_Write(vault, &keypair->value.data_len, sizeof(keypair->value.data_len)); // Read NOCACHE Entries from Backup file if (keypair->flags & ESIF_SERVICE_CONFIG_NOCACHE) { size_t offset = IOStream_GetOffset(vault); // Read Block from BAK file if (keypair->value.buf_len == 0) { size_t bakoffset = (size_t)keypair->value.buf_ptr; buffer = (UInt8*)esif_ccb_malloc(keypair->value.data_len); buffer_len = keypair->value.data_len; if (!buffer) { rc = ESIF_E_NO_MEMORY; break; } if (IOStream_Seek(vaultBak, bakoffset, SEEK_SET) != 0 || IOStream_Read(vaultBak, buffer, buffer_len) != buffer_len) { esif_ccb_free(buffer); rc = ESIF_E_UNSPECIFIED;// TODO: ESIF_E_IOERROR; break; } keypair->value.buf_ptr = (void*)offset; } // Convert internal storage to NOCACHE else { buffer = (UInt8*)keypair->value.buf_ptr; buffer_len = keypair->value.data_len; keypair->value.buf_ptr = (void*)offset; keypair->value.buf_len = 0; } } // Encrypt Data? if (keypair->flags & ESIF_SERVICE_CONFIG_ENCRYPT) { if (!buffer) { buffer = (UInt8*)esif_ccb_malloc(keypair->value.data_len); buffer_len = keypair->value.data_len; if (!buffer) { rc = ESIF_E_NO_MEMORY; break; } } for (byte = 0; byte < keypair->value.data_len; byte++) buffer[byte] = ~((UInt8*)(keypair->value.buf_ptr))[byte]; } if (buffer) { IOStream_Write(vault, buffer, buffer_len); esif_ccb_free(buffer); } else { IOStream_Write(vault, keypair->value.buf_ptr, keypair->value.data_len); } } } // Rollback on Error if (rc != ESIF_OK) { IOStream_Destroy(vaultBak); IOStream_Destroy(vault); esif_ccb_unlink(dv_file.filename); IGNORE_RESULT(esif_ccb_rename(dv_filebak.filename, dv_file.filename)); return rc; } // Remove BAK file and Commit if (vaultBak) { IOStream_Close(vaultBak); esif_ccb_unlink(dv_filebak.filename); IOStream_Destroy(vaultBak); } IOStream_Close(vault); IOStream_Destroy(vault); return rc; }