/* Set */ eEsifError DataVault_SetValue( DataVaultPtr self, EsifDataPtr path, EsifDataPtr value, esif_flags_t flags ) { eEsifError rc = ESIF_OK; DataCacheEntryPtr keypair; if (FLAGS_TEST(self->flags, ESIF_SERVICE_CONFIG_STATIC | ESIF_SERVICE_CONFIG_READONLY)) { return ESIF_E_READONLY; } // Ignore value for DELETEs if (FLAGS_TEST(flags, ESIF_SERVICE_CONFIG_DELETE)) { value = NULL; } // AUTO data types or AUTO_ALLOCATE are not allowed for SET if (value && (value->type == ESIF_DATA_AUTO || value->buf_len == ESIF_DATA_ALLOCATE)) { return ESIF_E_UNSUPPORTED_RESULT_DATA_TYPE; } // Reject SETs for static-sized data types whose buffer is too small if (value) { u32 len = (u32) esif_data_type_sizeof(value->type); if (len > 0 && value->buf_len < len) { value->data_len = len; return ESIF_E_NEED_LARGER_BUFFER; } } // Write to Log DataVault_WriteLog(self, (flags & ESIF_SERVICE_CONFIG_DELETE ? "DELETE" : "SET"), self->name, path, flags, value); // Delete DataVault Key(s)? if (esif_ccb_strpbrk((esif_string)path->buf_ptr, "*?") != NULL) { if (flags & ESIF_SERVICE_CONFIG_DELETE) { UInt32 item = 0; while (item < self->cache->size) { if (esif_ccb_strmatch((esif_string)self->cache->elements[item].key.buf_ptr, (esif_string)path->buf_ptr)) { flags |= FLAGS_TEST(self->cache->elements[item].flags, ESIF_SERVICE_CONFIG_PERSIST); if (DataCache_DeleteValue(self->cache, (esif_string)self->cache->elements[item].key.buf_ptr) == ESIF_OK) { continue; } } item++; } goto exit; } return ESIF_E_NOT_SUPPORTED; // Keys may not contain "*" or "?" } // Read data from File // TODO: Change Parser Logic and Syntax instead if (value && value->buf_ptr && esif_ccb_strncmp((char*)value->buf_ptr, "<<", 2) == 0) { void *buffer = 0; UInt32 buflen = 0; if (ReadFileIntoBuffer((char*)value->buf_ptr + 2, &buffer, &buflen) == ESIF_OK) { if (value->buf_len) { esif_ccb_free(value->buf_ptr); } value->buf_ptr = buffer; if (value->type == ESIF_DATA_STRING) { buflen++; // Include Null Terminator } value->buf_len = value->data_len = buflen; } else { return ESIF_E_UNSPECIFIED; // TODO: File Not Found } } // Get the Data Row or create it if it does not exist keypair = DataCache_GetValue(self->cache, (esif_string)path->buf_ptr); if (keypair) { // Match Found // READONLY? if (keypair->flags & ESIF_SERVICE_CONFIG_READONLY) { rc = ESIF_E_READONLY; } // DELETE? else if (flags & ESIF_SERVICE_CONFIG_DELETE) { flags |= keypair->flags; DataCache_DeleteValue(self->cache, (esif_string)path->buf_ptr); } else if (value && value->buf_ptr) { // UPDATE if (keypair->value.buf_len > 0 && value->data_len != keypair->value.buf_len) { void *new_buf = NULL; u32 new_buf_len = 0; // Grow or shrink buffer if it was allocated, otherwise ask for a larger buffer new_buf_len = esif_ccb_max(1, value->data_len); new_buf= (void *)esif_ccb_realloc(keypair->value.buf_ptr, new_buf_len); if (new_buf == NULL) { return ESIF_E_NEED_LARGER_BUFFER; } else { keypair->value.buf_len = new_buf_len; keypair->value.buf_ptr = new_buf; } } // Replace the File Offset stored in buf_ptr with a copy of the data for updated NOCACHE values if (keypair->flags & ESIF_SERVICE_CONFIG_NOCACHE && keypair->value.buf_len == 0) { keypair->value.buf_len = esif_ccb_max(1, value->data_len); keypair->value.buf_ptr = esif_ccb_malloc(value->buf_len); } keypair->flags = flags; keypair->value.type = value->type; keypair->value.data_len = value->data_len; esif_ccb_memcpy(keypair->value.buf_ptr, value->buf_ptr, value->data_len); rc = ESIF_OK; } } else if (value && value->buf_ptr && !(flags & ESIF_SERVICE_CONFIG_DELETE)) { EsifDataPtr valueClonePtr = NULL; // // The data passed in may be in a buffer owned elsewhere, so clone the data // valueClonePtr = EsifData_Clone(value); if (NULL == valueClonePtr) { rc = ESIF_E_NO_MEMORY; goto exit; } DataCache_InsertValue(self->cache, (esif_string)path->buf_ptr, valueClonePtr, flags); EsifData_Destroy(valueClonePtr); } exit: // If Persisted, Flush to disk if (rc == ESIF_OK && FLAGS_TEST(flags, ESIF_SERVICE_CONFIG_PERSIST)) { rc = DataVault_WriteVault(self); } return rc; }
/* Set */ eEsifError DataVault_SetValue ( DataVaultPtr self, EsifDataPtr path, EsifDataPtr value, esif_flags_t flags ) { eEsifError rc = ESIF_OK; DataCacheEntryPtr keypair; if (FLAGS_TEST(self->flags, ESIF_SERVICE_CONFIG_STATIC | ESIF_SERVICE_CONFIG_READONLY)) { return ESIF_E_READONLY; } // Ignore value for DELETEs if (FLAGS_TEST(flags, ESIF_SERVICE_CONFIG_DELETE)) { value = NULL; } // TODO: Locking // AUTO data types or AUTO_ALLOCATE are not allowed for SET if (value && (value->type == ESIF_DATA_AUTO || value->buf_len == ESIF_DATA_ALLOCATE)) { return ESIF_E_UNSUPPORTED_RESULT_DATA_TYPE; } // Write to Log DataVault_WriteLog(self, (flags & ESIF_SERVICE_CONFIG_DELETE ? "DELETE" : "SET"), self->name, path, flags, value); // Delete entire DataVault? if (strcmp((esif_string)path->buf_ptr, "*") == 0) { if (flags & ESIF_SERVICE_CONFIG_DELETE) { DataCache_Destroy(self->cache); if ((self->cache = DataCache_Create()) == NULL) { return ESIF_E_NO_MEMORY; } DataVault_WriteVault(self); return ESIF_OK; } return ESIF_E_NOT_SUPPORTED;// "*" is an invalid key value } // Read data from File // TODO: Change Parser Logic and Syntax instead if (value && value->buf_ptr && esif_ccb_strncmp((char*)value->buf_ptr, "<<", 2) == 0) { void *buffer = 0; UInt32 buflen = 0; if (DataVault_ReadFile(self, (char*)value->buf_ptr + 2, &buffer, &buflen) == ESIF_OK) { value->buf_ptr = buffer; if (value->type == ESIF_DATA_STRING) { buflen++; // Include Null Terminator } value->buf_len = value->data_len = buflen; } else { return ESIF_E_UNSPECIFIED; // TODO: File Not Found } } // Get the Data Row or create it if it does not exist keypair = DataCache_GetValue(self->cache, (esif_string)path->buf_ptr); if (keypair) { // Match Found // READONLY? if (keypair->flags & ESIF_SERVICE_CONFIG_READONLY) { rc = ESIF_E_READONLY; } // DELETE? else if (flags & ESIF_SERVICE_CONFIG_DELETE) { flags |= keypair->flags; DataCache_Delete(self->cache, (esif_string)path->buf_ptr); } else if (value && value->buf_ptr) { // UPDATE #ifdef ESIF_ATTR_OS_WINDOWS // Update Registry Value for REGKEY values if REGLINK is *NOT* specified in SET command if ((keypair->flags & ESIF_SERVICE_CONFIG_REGLINK) && !(flags & ESIF_SERVICE_CONFIG_REGLINK)) { keypair->value.type = value->type; rc = DataVault_WriteRegistry(self, (esif_string)keypair->value.buf_ptr, value); } else // ... #endif if (keypair->value.buf_len && value->data_len > keypair->value.buf_len) { rc = ESIF_E_NEED_LARGER_BUFFER; } else { keypair->flags = flags; keypair->value.type = value->type; keypair->value.data_len = value->data_len; // Replace the File Offset stored in buf_ptr with a copy of the data for updated NOCACHE values if (keypair->flags & ESIF_SERVICE_CONFIG_NOCACHE && keypair->value.buf_len == 0) { keypair->value.buf_ptr = esif_ccb_malloc(value->data_len); keypair->value.buf_len = value->data_len; } esif_ccb_memcpy(keypair->value.buf_ptr, value->buf_ptr, value->data_len); rc = ESIF_OK; } } } else if (value && value->buf_ptr && !(flags & ESIF_SERVICE_CONFIG_DELETE)) { // Copy Key/Value Pair to new Data Row EsifData newkey = {ESIF_DATA_STRING, esif_ccb_strdup((esif_string)path->buf_ptr), path->data_len, path->data_len}; EsifData newvalue = {value->type, esif_ccb_malloc(esif_ccb_max(value->buf_len, value->data_len)), value->data_len, value->data_len}; esif_ccb_memcpy(newvalue.buf_ptr, value->buf_ptr, value->data_len); DataCache_SetValue(self->cache, (esif_string)newkey.buf_ptr, newvalue, flags); esif_ccb_free(newkey.buf_ptr); } // If Persisted, Flush to disk if (rc == ESIF_OK && FLAGS_TEST(flags, ESIF_SERVICE_CONFIG_PERSIST)) { DataVault_WriteVault(self); } return rc; }
// Retrieve a single value from a DataVault eEsifError DataVault_GetValue( DataVaultPtr self, EsifDataPtr path, EsifDataPtr value, esif_flags_t *flagsPtr ) { eEsifError rc = ESIF_E_NOT_FOUND; DataCacheEntryPtr keypair = NULL; if (!self) return ESIF_E_PARAMETER_IS_NULL; if (flagsPtr) *flagsPtr = 0; // Return "keyname1|keyname2|..." if path contains "*" or "?" if (esif_ccb_strpbrk((esif_string)path->buf_ptr, "*?") != NULL) { EsifDataPtr nameSpace = EsifData_CreateAs(ESIF_DATA_STRING, esif_ccb_strdup(self->name), ESIFAUTOLEN, ESIFAUTOLEN); EsifDataPtr key = EsifData_CreateAs(ESIF_DATA_STRING, path->buf_ptr, 0, ESIFAUTOLEN); EsifConfigFindContext context = NULL; esif_string keylist = NULL; u32 data_len = 0; // Verify valid Data Type and Data Buffer size if (value->type != ESIF_DATA_STRING && value->type != ESIF_DATA_AUTO) { rc = ESIF_E_UNSUPPORTED_RESULT_DATA_TYPE; } if (rc == ESIF_E_NOT_FOUND && nameSpace != NULL && key != NULL && (rc = EsifConfigFindFirst(nameSpace, key, NULL, &context)) == ESIF_OK) { do { data_len += (u32)key->data_len; esif_string newlist = esif_ccb_realloc(keylist, data_len); if (newlist == NULL) { EsifData_Set(key, ESIF_DATA_STRING, "", 0, ESIFAUTOLEN); rc = ESIF_E_NO_MEMORY; break; } keylist = newlist; esif_ccb_sprintf_concat(data_len, keylist, "%s%s", (*keylist ? "|" : ""), (char *)key->buf_ptr); EsifData_Set(key, ESIF_DATA_STRING, path->buf_ptr, 0, ESIFAUTOLEN); } while ((rc = EsifConfigFindNext(nameSpace, key, NULL, &context)) == ESIF_OK); EsifConfigFindClose(&context); if (rc == ESIF_E_ITERATION_DONE) { rc = ESIF_OK; } } EsifData_Destroy(nameSpace); EsifData_Destroy(key); if (!keylist || rc != ESIF_OK) { esif_ccb_free(keylist); return rc; } // Return keylist value and data type if (value->type == ESIF_DATA_AUTO) { value->type = ESIF_DATA_STRING; } if (value->buf_len == ESIF_DATA_ALLOCATE) { esif_ccb_free(value->buf_ptr); value->buf_ptr = esif_ccb_strdup(keylist); value->buf_len = data_len; value->data_len = data_len; } else if (value->buf_len < data_len) { rc = ESIF_E_NEED_LARGER_BUFFER; value->data_len = data_len; } else if (value->buf_ptr) { esif_ccb_strcpy(value->buf_ptr, keylist, value->buf_len); value->data_len = data_len; } esif_ccb_free(keylist); return rc; } // Write to Log before retrieval if AUTO if (value->type == ESIF_DATA_AUTO || value->buf_len == ESIF_DATA_ALLOCATE) { DataVault_WriteLog(self, "AUTO", (esif_string)(self->name), path, 0, value); } keypair = DataCache_GetValue(self->cache, (esif_string)path->buf_ptr); if (NULL != keypair) { UInt32 data_len = keypair->value.data_len; void *buf_ptr = keypair->value.buf_ptr; UInt32 buf_len = 0; Bool buf_alloc = ESIF_FALSE; // File Redirect? if (keypair->flags & ESIF_SERVICE_CONFIG_FILELINK) { if (ReadFileIntoBuffer((esif_string)buf_ptr, &buf_ptr, &data_len) != ESIF_OK) { value->data_len = 0; if (value->type == ESIF_DATA_AUTO) { value->type = keypair->value.type; } if (value->buf_len == ESIF_DATA_ALLOCATE) { value->buf_len = 0; value->buf_ptr = 0; } return ESIF_OK; // return OK and a blank buffer if file not found/error } // Include Null Terminator if result is STRING if (value->buf_len == ESIF_DATA_ALLOCATE && (value->type == ESIF_DATA_STRING || (value->type == ESIF_DATA_AUTO && keypair->value.type == ESIF_DATA_STRING))) { data_len++; } buf_len = data_len; buf_alloc = ESIF_TRUE; } // Match Found. Verify Data Type matches unless AUTO if (value->type != keypair->value.type && value->type != ESIF_DATA_AUTO) { rc = ESIF_E_UNSUPPORTED_RESULT_DATA_TYPE; // TODO: ESIF_E_INVALID_DATA_TYPE } // Verify Data Buffer is large enough unless Auto-Allocate else if (value->buf_len < data_len && value->buf_len != ESIF_DATA_ALLOCATE) { value->data_len = data_len; rc = ESIF_E_NEED_LARGER_BUFFER; } // Return pointer to static contents if this is a static vault else if ((self->flags & ESIF_SERVICE_CONFIG_STATIC) && (value->type == ESIF_DATA_AUTO) && (value->buf_len == ESIF_DATA_ALLOCATE)) { value->type = keypair->value.type; value->data_len = data_len; value->buf_len = 0; // Caller MUST NOT Free! value->buf_ptr = buf_ptr; rc = ESIF_OK; } else { // Set Data Type and Auto-Allocate Buffer? if (value->type == ESIF_DATA_AUTO) { value->type = keypair->value.type; } if (ESIF_DATA_ALLOCATE == value->buf_len) { value->buf_len = esif_ccb_max(1, data_len); value->buf_ptr = esif_ccb_malloc(value->buf_len); if (!value->buf_ptr) { if (buf_alloc) { esif_ccb_free(buf_ptr); } return ESIF_E_NO_MEMORY; } } // Read from file if NOCACHE option if ((keypair->flags & ESIF_SERVICE_CONFIG_NOCACHE) && keypair->value.buf_len == 0) { size_t offset = (size_t)keypair->value.buf_ptr; if (DataVault_GetFromSource(self, (esif_string)value->buf_ptr, data_len, offset) != ESIF_OK) { if (buf_alloc) { esif_ccb_free(buf_ptr); } return ESIF_E_NOT_FOUND; } // Unscramble Data? if (keypair->flags & ESIF_SERVICE_CONFIG_SCRAMBLE) { UInt32 byte; for (byte = 0; byte < data_len; byte++) ((UInt8*)(value->buf_ptr))[byte] = ~((UInt8*)(value->buf_ptr))[byte]; } } else { esif_ccb_memcpy(value->buf_ptr, buf_ptr, data_len); } value->data_len = data_len; rc = ESIF_OK; } // Return flags if (rc == ESIF_OK) { if (flagsPtr != NULL) *flagsPtr = keypair->flags; } // Destroy Dynamically copied data, such as FILELINK contents if (buf_alloc) { esif_ccb_free(buf_ptr); } } // Write to Log DataVault_WriteLog(self, "GET", (esif_string)self->name, path, 0, value); return rc; }
// Retrieve a single value from a DataVault eEsifError DataVault_GetValue ( DataVaultPtr self, EsifDataPtr path, EsifDataPtr value ) { eEsifError rc = ESIF_E_NOT_FOUND; DataCacheEntryPtr keypair = NULL; if (!self) return ESIF_E_PARAMETER_IS_NULL; // TODO: Locking // Debug: Dump Entire Contents of DataVault if path="*" if (strcmp((esif_string)path->buf_ptr, "*") == 0) { UInt32 context = 0; EsifDataPtr nameSpace = EsifData_CreateAs(ESIF_DATA_STRING, esif_ccb_strdup(self->name), ESIFAUTOLEN, ESIFAUTOLEN); EsifDataPtr key = EsifData_CreateAs(ESIF_DATA_AUTO, NULL, ESIF_DATA_ALLOCATE, 0); EsifDataPtr value = EsifData_CreateAs(ESIF_DATA_AUTO, NULL, ESIF_DATA_ALLOCATE, 0); #ifdef _DEBUG // Dump DataCache if Debug Mode UInt32 i; for (i = 0; i < self->cache->size; i++) { DataCacheEntryPtr keypair = &self->cache->elements[i]; CMD_DEBUG("\n" "id=%d\n" "key=%s\n" "flags=%08X\n" "value.type = %s (%d)\n" "value.buf_ptr = %p %s\n" "value.buf_len = %d\n" "value.data_len= %d\n", i, (char*)keypair->key.buf_ptr, keypair->flags, esif_data_type_str(keypair->value.type), keypair->value.type, keypair->value.buf_ptr, ((keypair->flags & (ESIF_SERVICE_CONFIG_FILELINK | ESIF_SERVICE_CONFIG_REGLINK)) ? (esif_string)keypair->value.buf_ptr : ""), keypair->value.buf_len, keypair->value.data_len ); } if (i > 0) { CMD_DEBUG("*****************\n"); } #endif // Iterate the Contents of the Data Cache if ((rc = EsifConfigFindFirst(nameSpace, key, value, &context)) == ESIF_OK) { do { StringPtr valuestr = EsifData_ToString(value); CMD_DEBUG("\n" "EsifFind%s(\"%s\",%d):\n" " path = %s\n" " value= %s%s%s\n" " type = %s, len=%d\n", (context <= 1 ? "First" : "Next"), (char*)nameSpace->buf_ptr, context - 1, (char*)key->buf_ptr, (value->type == ESIF_DATA_STRING ? "\"" : ""), (valuestr ? valuestr : ""), (value->type == ESIF_DATA_STRING ? "\"" : ""), esif_data_type_str(value->type), value->data_len ); esif_ccb_free(valuestr); EsifData_Set(key, ESIF_DATA_AUTO, NULL, ESIF_DATA_ALLOCATE, 0); EsifData_Set(value, ESIF_DATA_AUTO, NULL, ESIF_DATA_ALLOCATE, 0); } while ((rc = EsifConfigFindNext(nameSpace, key, value, &context)) == ESIF_OK); if (rc == ESIF_E_NOT_FOUND) { rc = ESIF_OK; } } EsifData_Destroy(nameSpace); EsifData_Destroy(key); EsifData_Destroy(value); return ESIF_OK; } // Write to Log before retrieval if AUTO if (value->type == ESIF_DATA_AUTO || value->buf_len == ESIF_DATA_ALLOCATE) { DataVault_WriteLog(self, "AUTO", (esif_string)(self->name), path, 0, value); } keypair = DataCache_GetValue(self->cache, (esif_string)path->buf_ptr); if (NULL != keypair) { UInt32 data_len = keypair->value.data_len; void *buf_ptr = keypair->value.buf_ptr; // File Redirect? if (keypair->flags & ESIF_SERVICE_CONFIG_FILELINK) { if (DataVault_ReadFile(self, (esif_string)buf_ptr, &buf_ptr, &data_len) != ESIF_OK) { value->data_len = 0; if (value->type == ESIF_DATA_AUTO) { value->type = keypair->value.type; } if (value->buf_len == ESIF_DATA_ALLOCATE) { value->buf_len = 0; value->buf_ptr = 0; } return ESIF_OK; // return OK and a blank buffer if file not found/error } } #ifdef ESIF_ATTR_OS_WINDOWS // Registry Redirect? else if (keypair->flags & ESIF_SERVICE_CONFIG_REGLINK) { if (DataVault_ReadRegistry(self, (esif_string)buf_ptr, &buf_ptr, &data_len) != ESIF_OK) { value->data_len = 0; if (value->type == ESIF_DATA_AUTO) { value->type = keypair->value.type; } if (value->buf_len == ESIF_DATA_ALLOCATE) { value->buf_len = 0; value->buf_ptr = 0; } return ESIF_OK; // return OK and a blank buffer if Registry value not found/error } } #endif // Match Found. Verify Data Type matches unless AUTO if (value->type != keypair->value.type && value->type != ESIF_DATA_AUTO) { rc = ESIF_E_UNSUPPORTED_RESULT_DATA_TYPE; // TODO: ESIF_E_INVALID_DATA_TYPE } // Verify Data Buffer is large enough unless Auto-Allocate else if (value->buf_len < data_len && value->buf_len != ESIF_DATA_ALLOCATE) { value->buf_len = data_len; rc = ESIF_E_NEED_LARGER_BUFFER; } // Return pointer to static contents if this is a static vault else if ((self->flags & ESIF_SERVICE_CONFIG_STATIC) && (value->type == ESIF_DATA_AUTO) && (value->buf_len == ESIF_DATA_ALLOCATE)) { value->type = keypair->value.type; value->data_len = data_len; value->buf_len = 0; // Caller MUST NOT Free! value->buf_ptr = buf_ptr; rc = ESIF_OK; } else { // Set Data Type and Auto-Allocate Buffer? if (value->type == ESIF_DATA_AUTO) { value->type = keypair->value.type; } if (ESIF_DATA_ALLOCATE == value->buf_len) { value->buf_len = data_len; value->buf_ptr = esif_ccb_malloc(value->buf_len); if (!value->buf_ptr) { return ESIF_E_NO_MEMORY; } } // Read from file if NOCACHE option if ((keypair->flags & ESIF_SERVICE_CONFIG_NOCACHE) && keypair->value.buf_len == 0) { size_t offset = (size_t)keypair->value.buf_ptr; if (DataVault_ReadBlock(self, (esif_string)value->buf_ptr, data_len, offset) != ESIF_OK) { data_len = 0; return ESIF_E_NOT_FOUND; } // Decrypt? if (keypair->flags & ESIF_SERVICE_CONFIG_ENCRYPT) { UInt32 byte; for (byte = 0; byte < data_len; byte++) ((UInt8*)(value->buf_ptr))[byte] = ~((UInt8*)(value->buf_ptr))[byte]; } } else { esif_ccb_memcpy(value->buf_ptr, buf_ptr, data_len); } value->data_len = data_len; rc = ESIF_OK; } } // Write to Log DataVault_WriteLog(self, "GET", (esif_string)self->name, path, 0, value); return rc; }