示例#1
0
/* 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;
}
示例#2
0
/* 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;
}