// Resize an IString buffer (if dynamically allocated) ZString IString_Resize ( IStringPtr self, u32 buf_len ) { ESIF_ASSERT(self); // Allocate initial buffer if it has never been allocated if (self->buf_ptr == 0) { self->buf_ptr = esif_ccb_malloc(buf_len); if (self->buf_ptr) { self->buf_len = buf_len; self->data_len = 1; return (ZString)self->buf_ptr; } } // Resize buffer if it is not a static string if (self->buf_len > 0) { ZString buf_ptr = (ZString)esif_ccb_realloc(self->buf_ptr, buf_len); if (buf_ptr) { if (buf_len > self->buf_len) { esif_ccb_memset(buf_ptr + self->buf_len, 0, buf_len - self->buf_len); } self->buf_ptr = buf_ptr; self->buf_len = buf_len; return (ZString)self->buf_ptr; } } return 0; }
void StringList_Add ( StringListPtr self, char *str ) { ESIF_ASSERT(str); self->list = (char**)esif_ccb_realloc(self->list, (self->items + 2) * sizeof(self->list[0])); if (self->list) { self->list[self->items++] = String_Clone(str); self->list[self->items] = 0; } }
// 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; }
/* 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; }
/* Copy/Merge Keys from one NameSpace to Another */ eEsifError EsifConfigCopy( EsifDataPtr nameSpaceFrom, // Source DV EsifDataPtr nameSpaceTo, // Target DV EsifDataPtr keyspecs, // Tab-separated Keyspec List (wildcards OK) esif_flags_t flags, // Item Flags Bool replaceKeys, // TRUE=COPY Keys (Replace if exists), FALSE=MERGE Keys (Do Not Replace) UInt32 *keycount) // Optional pointer to variable to hold Key Count copied/merged { eEsifError rc = ESIF_OK; EsifConfigFindContext context = NULL; EsifDataPtr data_key = NULL; EsifDataPtr data_value = NULL; esif_string keylist = NULL; esif_string keyspec = NULL; esif_string keyspec_context = NULL; char **keyset = NULL; size_t keyset_count = 0; UInt32 exported = 0; esif_context_t qsort_ctx = 0; size_t key = 0; ESIF_ASSERT(nameSpaceFrom && nameSpaceTo && keyspecs && nameSpaceFrom->buf_ptr && nameSpaceTo->buf_ptr && keyspecs->buf_ptr); // Parse Key List (optionally Tab-separated) keylist = esif_ccb_strdup((esif_string)keyspecs->buf_ptr); if (keylist == NULL) { rc = ESIF_E_NO_MEMORY; goto exit; } // Create sorted keyset with exclude keyspecs ("!keyspec") listed first keyspec = esif_ccb_strtok(keylist, "\t", &keyspec_context); while (keyspec != NULL) { char **new_keyset = (char **)esif_ccb_realloc(keyset, sizeof(char *) * (keyset_count + 1)); if (new_keyset == NULL) { rc = ESIF_E_NO_MEMORY; goto exit; } keyset = new_keyset; keyset[keyset_count++] = keyspec; keyspec = esif_ccb_strtok(NULL, "\t", &keyspec_context); } esif_ccb_qsort(keyset, keyset_count, sizeof(char *), esif_ccb_qsort_stricmp, qsort_ctx); // Enumerate Each Matching keyspec for (key = 0; (rc == ESIF_OK && key < keyset_count); key++) { // Skip excludes for now so we can compare to each maching keyspec later if (keyset[key][0] == '!') { continue; } EsifData_Destroy(data_key); data_key = EsifData_CreateAs(ESIF_DATA_STRING, keyset[key], 0, ESIFAUTOLEN); if (data_key == NULL) { rc = ESIF_E_NO_MEMORY; goto exit; } if ((rc = EsifConfigFindFirst(nameSpaceFrom, data_key, NULL, &context)) == ESIF_OK) { do { // Skip if matching key matches any exclude keyspecs Bool skip_key = ESIF_FALSE; size_t ex = 0; for (ex = 0; (ex < key && keyset[ex][0] == '!'); ex++) { if (esif_ccb_strmatch((esif_string)data_key->buf_ptr, &keyset[ex][1])) { skip_key = ESIF_TRUE; break; } } // copy = always replace existing key in target if it already exists // merge = never replace existing key in target if it already exists if ((skip_key == ESIF_FALSE) && (replaceKeys == ESIF_TRUE || DataBank_KeyExists(g_DataBankMgr, (esif_string)nameSpaceTo->buf_ptr, (esif_string)data_key->buf_ptr) == ESIF_FALSE)) { EsifData_Destroy(data_value); data_value = EsifData_CreateAs(ESIF_DATA_AUTO, NULL, ESIF_DATA_ALLOCATE, 0); if (data_value == NULL) { rc = ESIF_E_NO_MEMORY; break; } rc = EsifConfigGet(nameSpaceFrom, data_key, data_value); if (rc != ESIF_OK) { break; } rc = EsifConfigSet(nameSpaceTo, data_key, flags, data_value); if (rc != ESIF_OK) { break; } ESIF_TRACE_DEBUG("DV %s: @%s => @%s [%s] {%s, %u bytes}\n", (replaceKeys ? "Copy" : "Merge"), (esif_string)nameSpaceFrom->buf_ptr, (esif_string)nameSpaceTo->buf_ptr, (esif_string)data_key->buf_ptr, esif_data_type_str(data_value->type), data_value->data_len); exported++; } // Reset Key for next search EsifData_Set(data_key, ESIF_DATA_STRING, keyset[key], 0, ESIFAUTOLEN); } while ((rc = EsifConfigFindNext(nameSpaceFrom, data_key, NULL, &context)) == ESIF_OK); EsifConfigFindClose(&context); } if (rc == ESIF_E_ITERATION_DONE || rc == ESIF_E_NOT_FOUND) { rc = ESIF_OK; } } exit: if (rc == ESIF_OK && keycount != NULL) { *keycount = exported; } EsifData_Destroy(data_key); EsifData_Destroy(data_value); esif_ccb_free(keylist); esif_ccb_free(keyset); return rc; }