static void MsgSetCatalog(const char *domain, MsgCatalog *catalog) { MsgState *state = MsgGetState(); ASSERT(domain); if (state->domains == NULL) { state->domains = HashTable_Alloc(8, HASH_STRING_KEY | HASH_FLAG_COPYKEY, (HashTableFreeEntryFn) MsgCatalogFree); ASSERT_MEM_ALLOC(state->domains); } HashTable_ReplaceOrInsert(state->domains, domain, catalog); }
static GuestInfoCollector * GuestInfoConstructCollector(GuestInfoQuery *queries, // IN: uint32 numQueries) // IN: { uint32 i; uint32 regExp = 0; GuestInfoCollector *collector = calloc(1, sizeof *collector); if (collector == NULL) { return NULL; } collector->reportMap = HashTable_Alloc(256, HASH_INT_KEY, NULL); collector->exactMatches = HashTable_Alloc(256, HASH_STRING_KEY | HASH_FLAG_COPYKEY, NULL); collector->numRegExps = 0; for (i = 0; i < numQueries; i++) { if (queries[i].isRegExp && queries[i].collect) { collector->numRegExps++; } } collector->numStats = numQueries; collector->stats = calloc(numQueries, sizeof *collector->stats); collector->regExps = calloc(collector->numRegExps, sizeof(GuestInfoStat *)); if ((collector->exactMatches == NULL) || (collector->reportMap == NULL) || ((collector->numRegExps != 0) && (collector->regExps == NULL)) || ((collector->numStats != 0) && (collector->stats == NULL))) { GuestInfoDestroyCollector(collector); return NULL; } regExp = 0; for (i = 0; i < numQueries; i++) { GuestInfoQuery *query = &queries[i]; GuestInfoStat *stat = &collector->stats[i]; ASSERT(query->reportID); stat->query = query; if (!query->collect) { continue; } if (query->isRegExp) { ASSERT(query->locatorString); collector->regExps[regExp++] = stat; } else { if (query->locatorString != NULL) { HashTable_Insert(collector->exactMatches, query->locatorString, stat); } } /* The report lookup */ HashTable_Insert(collector->reportMap, INT_AS_HASHKEY(query->reportID), stat); } return collector; }
MXUserRWLock * MXUser_CreateRWLock(const char *userName, // IN: MX_Rank rank) // IN: { Bool lockInited; char *properName; MXUserRWLock *lock; Bool useNative = MXUserNativeRWSupported(); lock = Util_SafeCalloc(1, sizeof(*lock)); if (userName == NULL) { if (LIKELY(useNative)) { properName = Str_SafeAsprintf(NULL, "RW-%p", GetReturnAddress()); } else { /* emulated */ properName = Str_SafeAsprintf(NULL, "RWemul-%p", GetReturnAddress()); } } else { properName = Util_SafeStrdup(userName); } lock->header.signature = MXUserGetSignature(MXUSER_TYPE_RW); lock->header.name = properName; lock->header.rank = rank; lock->header.serialNumber = MXUserAllocSerialNumber(); lock->header.dumpFunc = MXUserDumpRWLock; /* * Always attempt to use native locks when they are available. If, for some * reason, a native lock should be available but isn't, fall back to using * an internal recursive lock - something is better than nothing. */ lock->useNative = useNative && MXUserNativeRWInit(&lock->nativeLock); lockInited = MXRecLockInit(&lock->recursiveLock); if (LIKELY(lockInited)) { Bool doStats; lock->holderTable = HashTable_Alloc(256, HASH_INT_KEY | HASH_FLAG_ATOMIC, MXUserFreeHashEntry); if (vmx86_stats) { doStats = MXUserStatsEnabled(); } else { doStats = FALSE; } if (doStats) { MXUser_ControlRWLock(lock, MXUSER_CONTROL_ENABLE_STATS); } else { lock->header.statsFunc = NULL; Atomic_WritePtr(&lock->statsMem, NULL); } MXUserAddToList(&lock->header); } else { if (lock->useNative) { MXUserNativeRWDestroy(&lock->nativeLock); } free(properName); free(lock); lock = NULL; } return lock; }
MXUserRWLock * MXUser_CreateRWLock(const char *userName, // IN: MX_Rank rank) // IN: { Bool lockInited; char *properName; Bool useNative = MXUserNativeRWSupported(); MXUserRWLock *lock = Util_SafeCalloc(1, sizeof *lock); if (userName == NULL) { if (LIKELY(useNative)) { properName = Str_SafeAsprintf(NULL, "RW-%p", GetReturnAddress()); } else { /* emulated */ properName = Str_SafeAsprintf(NULL, "RWemul-%p", GetReturnAddress()); } } else { properName = Util_SafeStrdup(userName); } lock->header.signature = MXUserGetSignature(MXUSER_TYPE_RW); lock->header.name = properName; lock->header.rank = rank; lock->header.bits.serialNumber = MXUserAllocSerialNumber(); lock->header.dumpFunc = MXUserDumpRWLock; /* * Always attempt to use native locks when they are available. If, for some * reason, a native lock should be available but isn't, fall back to using * an internal recursive lock - something is better than nothing. */ lock->useNative = useNative && MXUserNativeRWInit(&lock->nativeLock); lockInited = MXRecLockInit(&lock->recursiveLock); if (LIKELY(lockInited)) { uint32 statsMode; lock->holderTable = HashTable_Alloc(256, HASH_INT_KEY | HASH_FLAG_ATOMIC, MXUserFreeHashEntry); statsMode = MXUserStatsMode(); switch (MXUserStatsMode()) { case 0: MXUserDisableStats(&lock->acquireStatsMem, &lock->heldStatsMem); lock->header.statsFunc = NULL; break; case 1: MXUserEnableStats(&lock->acquireStatsMem, NULL); lock->header.statsFunc = MXUserStatsActionRW; break; case 2: MXUserEnableStats(&lock->acquireStatsMem, &lock->heldStatsMem); lock->header.statsFunc = MXUserStatsActionRW; break; default: Panic("%s: unknown stats mode: %d!\n", __FUNCTION__, statsMode); } MXUserAddToList(&lock->header); } else { Panic("%s: native lock initialization routine failed\n", __FUNCTION__); } return lock; }
static HashTable * SNEBuildHash(const char **compatEnviron) // IN: original "compatibility" environment { HashTable *environTable; const char **p; /* * Number of buckets picked arbitrarily. We're more interested in having an * associative array than raw table performance. */ environTable = HashTable_Alloc(64, HASH_STRING_KEY | HASH_FLAG_COPYKEY, free); for (p = compatEnviron; p && *p; p++) { const size_t prefixLength = sizeof "VMWARE_" - 1; char *key; char *value; unsigned int index; index = 0; key = StrUtil_GetNextToken(&index, *p, "="); if (!key) { /* XXX Must empty environment variables still contain a '=' delimiter? */ Debug("%s: Encountered environment entry without '='.\n", __func__); continue; } /* * Copy the value beginning after the '=' delimiter (even if it's empty). */ ++index; value = Util_SafeStrdup(&(*p)[index]); if (StrUtil_StartsWith(key, "VMWARE_") && key[prefixLength] != '\0' && (value[0] == '0' || value[0] == '1')) { /* * Okay, this appears to be one of the wrapper's variables, so let's * figure out the original environment variable name (by just indexing * past the prefix) and value (by indexing past the "was this variable * in the native environment?" marker). * * XXX Should we move this marker to a separate header? */ char *realKey = &key[prefixLength]; char *realValue = (value[0] == '0') ? NULL : Util_SafeStrdup(&value[1]); HashTable_ReplaceOrInsert(environTable, realKey, realValue); } else { HashTable_LookupOrInsert(environTable, key, value); } /* * The hash table makes a copy of our key, and it takes ownership of inserted * values (via our passed freeing function). So that means we're responsible * for freeing 'key', but -not- 'value'. */ free(key); } return environTable; }
static MsgCatalog * MsgLoadCatalog(const char *path) { gchar *localPath; GError *err = NULL; GIOChannel *stream; gboolean error = FALSE; MsgCatalog *catalog = NULL; HashTable *dict; ASSERT(path != NULL); localPath = VMTOOLS_GET_FILENAME_LOCAL(path, NULL); ASSERT(localPath != NULL); stream = g_io_channel_new_file(localPath, "r", &err); VMTOOLS_RELEASE_FILENAME_LOCAL(localPath); if (err != NULL) { g_debug("Unable to open '%s': %s\n", path, err->message); g_clear_error(&err); return NULL; } dict = HashTable_Alloc(8, HASH_STRING_KEY | HASH_FLAG_COPYKEY, g_free); ASSERT_MEM_ALLOC(dict); for (;;) { gboolean eof = FALSE; char *name = NULL; char *value = NULL; gchar *line; /* Read the next key / value pair. */ for (;;) { gsize i; gsize len; gsize term; char *unused = NULL; gboolean cont = FALSE; g_io_channel_read_line(stream, &line, &len, &term, &err); if (err != NULL) { g_warning("Unable to read a line from '%s': %s\n", path, err->message); g_clear_error(&err); error = TRUE; g_free(line); break; } if (line == NULL) { eof = TRUE; break; } /* * Fix the line break to always be Unix-style, to make lib/dict * happy. */ if (line[term] == '\r') { line[term] = '\n'; if (len > term) { line[term + 1] = '\0'; } } /* * If currently name is not NULL, then check if this is a continuation * line and, if it is, just append the contents to the current value. */ if (term > 0 && name != NULL && line[term - 1] == '"') { for (i = 0; i < len; i++) { if (line[i] == '"') { /* OK, looks like a continuation line. */ char *tmp; char *unescaped; line[term - 1] = '\0'; unescaped = Escape_Undo('|', line + i + 1, len - i, NULL); tmp = Str_Asprintf(NULL, "%s%s", value, unescaped); free(unescaped); free(value); value = tmp; cont = TRUE; break; } else if (line[i] != ' ' && line[i] != '\t') { break; } } } /* * If not a continuation line and we have a name, break out of the * inner loop to update the dictionaty. */ if (!cont && name != NULL) { g_free(line); break; } /* * Finally, try to parse the string using the dictionary library. */ if (!cont && DictLL_UnmarshalLine(line, len, &unused, &name, &value) == NULL) { g_warning("Couldn't parse line from catalog: %s", line); error = TRUE; } g_free(line); free(unused); } if (error) { break; } if (name != NULL) { ASSERT(value); if (!Unicode_IsBufferValid(name, strlen(name) + 1, STRING_ENCODING_UTF8) || !Unicode_IsBufferValid(value, strlen(value) + 1, STRING_ENCODING_UTF8)) { g_warning("Invalid UTF-8 string in message catalog (key = %s)\n", name); error = TRUE; break; } MsgUnescape(value); HashTable_ReplaceOrInsert(dict, name, g_strdup(value)); free(name); free(value); name = NULL; value = NULL; } if (eof) { break; } } g_io_channel_unref(stream); if (error) { HashTable_Free(dict); dict = NULL; } else { catalog = g_new0(MsgCatalog, 1); catalog->utf8 = dict; } return catalog; }
static const void * MsgGetString(const char *domain, const char *msgid, StringEncoding encoding) { const char *idp; const char *strp; char idBuf[MSG_MAX_ID]; size_t len; HashTable *source = NULL; MsgCatalog *catalog; MsgState *state = MsgGetState(); /* All message strings must be prefixed by the message ID. */ ASSERT(domain != NULL); ASSERT(msgid != NULL); ASSERT(MsgHasMsgID(msgid)); #if defined(_WIN32) ASSERT(encoding == STRING_ENCODING_UTF8 || encoding == STRING_ENCODING_UTF16_LE); #else ASSERT(encoding == STRING_ENCODING_UTF8); #endif /* * Find the beginning of the ID (idp) and the string (strp). * The string should have the correct MSG_MAGIC(...)... form. */ idp = msgid + MSG_MAGIC_LEN + 1; strp = strchr(idp, ')') + 1; len = strp - idp - 1; ASSERT_NOT_IMPLEMENTED(len <= MSG_MAX_ID - 1); memcpy(idBuf, idp, len); idBuf[len] = '\0'; /* * This lock is pretty coarse-grained, but a lot of the code below just runs * in exceptional situations, so it should be OK. */ g_static_mutex_lock(&state->lock); catalog = MsgGetCatalog(domain); if (catalog != NULL) { switch (encoding) { case STRING_ENCODING_UTF8: source = catalog->utf8; break; #if defined(_WIN32) case STRING_ENCODING_UTF16_LE: source = catalog->utf16; break; #endif default: NOT_IMPLEMENTED(); } } #if defined(_WIN32) /* * Lazily create the local and UTF-16 dictionaries. This may require also * registering an empty message catalog for the desired domain. */ if (source == NULL && encoding == STRING_ENCODING_UTF16_LE) { catalog = MsgGetCatalog(domain); if (catalog == NULL) { if (domain == NULL) { g_error("Application did not set up a default text domain."); } catalog = g_new0(MsgCatalog, 1); MsgSetCatalog(domain, catalog); } catalog->utf16 = HashTable_Alloc(8, HASH_STRING_KEY, g_free); ASSERT_MEM_ALLOC(catalog->utf16); source = catalog->utf16; } #endif /* * Look up the localized string, converting to requested encoding as needed. */ if (source != NULL) { const void *retval = NULL; if (HashTable_Lookup(source, idBuf, (void **) &retval)) { strp = retval; #if defined(_WIN32) } else if (encoding == STRING_ENCODING_UTF16_LE) { gchar *converted; Bool success; /* * Look up the string in UTF-8, convert it and cache it. */ retval = MsgGetString(domain, msgid, STRING_ENCODING_UTF8); ASSERT(retval); converted = (gchar *) g_utf8_to_utf16(retval, -1, NULL, NULL, NULL); ASSERT(converted != NULL); success = HashTable_Insert(source, idBuf, converted); ASSERT(success); strp = converted; #endif } } g_static_mutex_unlock(&state->lock); return strp; }