Bool SyncDriver_Freeze(const char *userPaths, // IN Bool enableNullDriver, // IN SyncDriverHandle *handle) // OUT { char *paths = NULL; SyncDriverErr err = SD_UNAVAILABLE; size_t i = 0; /* * First, convert the given path list to something the backends will * understand: a colon-separated list of paths. * * NOTE: Ignore disk UUIDs. We ignore the userPaths if it does * not start with '/' because all paths are absolute and it is * possible only when we get diskUUID as userPaths. So, all * mount points are considered instead of the userPaths provided. */ if (userPaths == NULL || Str_Strncmp(userPaths, "all", sizeof "all") == 0 || *userPaths != '/') { paths = SyncDriverListMounts(); if (paths == NULL) { Debug(LGPFX "Failed to list mount points.\n"); return SD_ERROR; } } else { /* * The sync driver API specifies spaces as separators, but the driver * uses colons as the path separator on Unix. */ char *c; paths = Util_SafeStrdup(userPaths); for (c = paths; *c != '\0'; c++) { if (*c == ' ') { *c = ':'; } } } while (err == SD_UNAVAILABLE && i < ARRAYSIZE(gBackends)) { SyncFreezeFn freezeFn = gBackends[i]; Debug(LGPFX "Calling backend %d.\n", (int) i); i++; #if defined(__linux__) && !defined(USERWORLD) if (!enableNullDriver && (freezeFn == NullDriver_Freeze)) { Debug(LGPFX "Skipping nullDriver backend.\n"); continue; } #endif err = freezeFn(paths, handle); } free(paths); return err == SD_SUCCESS; }
static Bool SyncDriverIsRemoteFSType(const char *fsType) { size_t i; for (i = 0; i < ARRAYSIZE(gRemoteFSTypes); i++) { if (Str_Strncmp(fsType, gRemoteFSTypes[i], sizeof gRemoteFSTypes[i]) == 0) { return TRUE; } } return FALSE; }
char * File_PrependToPath(const char *searchPath, // IN: const char *elem) // IN: { const char sep = FILE_SEARCHPATHTOKEN[0]; char *newPath; char *path; size_t n; ASSERT(searchPath); ASSERT(elem); newPath = Str_SafeAsprintf(NULL, "%s%s%s", elem, FILE_SEARCHPATHTOKEN, searchPath); n = strlen(elem); path = newPath + n + 1; for (;;) { char *next = Str_Strchr(path, sep); size_t len = next ? next - path : strlen(path); if ((len == n) && (Str_Strncmp(path, elem, len) == 0)) { if (next) { memmove(path, next + 1, strlen(next + 1) + 1); } else { *--path = '\0'; } break; } if (!next) { break; } path = next + 1; } return newPath; }
Bool SyncDriver_Freeze(const char *userPaths, // IN SyncDriverHandle *handle) // OUT { char *paths = NULL; SyncDriverErr err = SD_UNAVAILABLE; size_t i = 0; /* * First, convert the given path list to something the backends will * understand: a colon-separated list of paths. */ if (userPaths == NULL || Str_Strncmp(userPaths, "all", sizeof "all") == 0) { paths = SyncDriverListMounts(); if (paths == NULL) { Debug(LGPFX "Failed to list mount points.\n"); return SD_ERROR; } } else { /* * The sync driver API specifies spaces as separators, but the driver * uses colons as the path separator on Unix. */ char *c; paths = Util_SafeStrdup(userPaths); for (c = paths; *c != '\0'; c++) { if (*c == ' ') { *c = ':'; } } } while (err == SD_UNAVAILABLE && i < ARRAYSIZE(gBackends)) { err = gBackends[i++](paths, handle); } free(paths); return err == SD_SUCCESS; }
Unicode File_StripSlashes(ConstUnicode path) // IN: { Unicode result, volume, dir, base; /* * SplitName handles all drive letter/UNC/whatever cases, all we * have to do is make sure the dir part is stripped of slashes if * there isn't a base part. */ File_SplitName(path, &volume, &dir, &base); if (!Unicode_IsEmpty(dir) && Unicode_IsEmpty(base)) { char *dir2 = Unicode_GetAllocBytes(dir, STRING_ENCODING_UTF8); size_t i = strlen(dir2); /* * Don't strip first slash on Windows, since we want at least * one slash to trail a drive letter/colon or UNC specifier. */ #if defined(_WIN32) while ((i > 1) && (('/' == dir2[i - 1]) || ('\\' == dir2[i - 1]))) { #else while ((i > 0) && ('/' == dir2[i - 1])) { #endif i--; } Unicode_Free(dir); dir = Unicode_AllocWithLength(dir2, i, STRING_ENCODING_UTF8); free(dir2); } result = Unicode_Join(volume, dir, base, NULL); Unicode_Free(volume); Unicode_Free(dir); Unicode_Free(base); return result; } /* *----------------------------------------------------------------------------- * * File_MapPathPrefix -- * * Given a path and a newPrefix -> oldPrefix mapping, transform * oldPath according to the mapping. * * Results: * The new path, or NULL if there is no mapping. * * Side effects: * The returned string is allocated, free it. * *----------------------------------------------------------------------------- */ char * File_MapPathPrefix(const char *oldPath, // IN: const char **oldPrefixes, // IN: const char **newPrefixes, // IN: size_t numPrefixes) // IN: { int i; size_t oldPathLen = strlen(oldPath); for (i = 0; i < numPrefixes; i++) { char *newPath; char *oldPrefix; char *newPrefix; size_t oldPrefixLen; oldPrefix = File_StripSlashes(oldPrefixes[i]); newPrefix = File_StripSlashes(newPrefixes[i]); oldPrefixLen = strlen(oldPrefix); /* * If the prefix matches on a DIRSEPS boundary, or the prefix is the * whole string, replace it. * * If we don't insist on matching a whole directory name, we could * mess things of if one directory is a substring of another. * * Perform a case-insensitive compare on Windows. (There are * case-insensitive filesystems on MacOS also, but the problem * is more acute with Windows because of frequent drive-letter * case mismatches. So in lieu of actually asking the * filesystem, let's just go with a simple ifdef for now.) */ if ((oldPathLen >= oldPrefixLen) && #ifdef _WIN32 (Str_Strncasecmp(oldPath, oldPrefix, oldPrefixLen) == 0) && #else (Str_Strncmp(oldPath, oldPrefix, oldPrefixLen) == 0) && #endif (strchr(VALID_DIRSEPS, oldPath[oldPrefixLen]) || (oldPath[oldPrefixLen] == '\0'))) { size_t newPrefixLen = strlen(newPrefix); size_t newPathLen = (oldPathLen - oldPrefixLen) + newPrefixLen; ASSERT(newPathLen > 0); ASSERT(oldPathLen >= oldPrefixLen); newPath = Util_SafeMalloc((newPathLen + 1) * sizeof(char)); memcpy(newPath, newPrefix, newPrefixLen); memcpy(newPath + newPrefixLen, oldPath + oldPrefixLen, oldPathLen - oldPrefixLen + 1); /* * It should only match once. Weird self-referencing mappings * aren't allowed. */ free(oldPrefix); free(newPrefix); return newPath; } free(oldPrefix); free(newPrefix); } return NULL; }
static VMGuestLibError VMGuestLibUpdateInfo(VMGuestLibHandle handle) // IN { char *reply = NULL; size_t replyLen; VMGuestLibError ret = VMGUESTLIB_ERROR_INVALID_ARG; uint32 hostVersion = HANDLE_VERSION(handle); /* * Starting with the highest supported protocol (major) version, negotiate * down to the highest host supported version. Host supports minimum version * 2. */ if (hostVersion == 0) { hostVersion = VMGUESTLIB_DATA_VERSION; } do { char commandBuf[64]; unsigned int index = 0; /* Free the last reply when retrying. */ free(reply); reply = NULL; /* * Construct command string with the command name and the version * of the data struct that we want. */ Str_Sprintf(commandBuf, sizeof commandBuf, "%s %d", VMGUESTLIB_BACKDOOR_COMMAND_STRING, hostVersion); /* Send the request. */ if (RpcChannel_SendOne(&reply, &replyLen, commandBuf)) { VMGuestLibDataV2 *v2reply = (VMGuestLibDataV2 *)reply; VMSessionId sessionId = HANDLE_SESSIONID(handle); ASSERT(hostVersion == v2reply->hdr.version); if (sessionId != 0 && sessionId != v2reply->hdr.sessionId) { /* Renegotiate protocol if sessionId changed. */ hostVersion = VMGUESTLIB_DATA_VERSION; HANDLE_SESSIONID(handle) = 0; continue; } ret = VMGUESTLIB_ERROR_SUCCESS; break; } /* * Host is older and doesn't support the requested protocol version. * Request the highest version the host supports. */ Debug("Failed to retrieve info: %s\n", reply ? reply : "NULL"); if (hostVersion == 2 || Str_Strncmp(reply, "Unknown command", sizeof "Unknown command") == 0) { /* * Host does not support this feature. Older (v2) host would return * "Unsupported version" if it doesn't recognize the requested version. * * XXX: Maybe use another error code for this case where the host * product doesn't support this feature? */ ret = VMGUESTLIB_ERROR_NOT_ENABLED; break; } else if (hostVersion == 3) { /* * Host supports v2 at a minimum. If request for v3 fails, then just use * v2, since v2 host does not send the highest supported version in the * reply. */ hostVersion = 2; HANDLE_SESSIONID(handle) = 0; continue; } else if (!StrUtil_GetNextUintToken(&hostVersion, &index, reply, ":")) { /* * v3 and onwards, the host returns the highest major version it supports, * if the requested version is not supported. So parse out the host * version from the reply and return error if it didn't. */ Debug("Bad reply received from host.\n"); ret = VMGUESTLIB_ERROR_OTHER; break; } ASSERT(hostVersion < VMGUESTLIB_DATA_VERSION); } while (ret != VMGUESTLIB_ERROR_SUCCESS); if (ret != VMGUESTLIB_ERROR_SUCCESS) { goto done; } /* Sanity check the results. */ if (replyLen < sizeof hostVersion) { Debug("Unable to retrieve version\n"); ret = VMGUESTLIB_ERROR_OTHER; goto done; } if (hostVersion == 2) { VMGuestLibDataV2 *v2reply = (VMGuestLibDataV2 *)reply; size_t dataSize = sizeof *v2reply; /* More sanity checks. */ if (v2reply->hdr.version != hostVersion) { Debug("Incorrect data version returned\n"); ret = VMGUESTLIB_ERROR_OTHER; goto done; } if (replyLen != dataSize) { Debug("Incorrect data size returned\n"); ret = VMGUESTLIB_ERROR_OTHER; goto done; } /* Store the reply in the handle. */ HANDLE_VERSION(handle) = v2reply->hdr.version; HANDLE_SESSIONID(handle) = v2reply->hdr.sessionId; if (HANDLE_DATASIZE(handle) < dataSize) { /* [Re]alloc if the local handle buffer is not big enough. */ free(HANDLE_DATA(handle)); HANDLE_DATA(handle) = Util_SafeCalloc(1, dataSize); HANDLE_DATASIZE(handle) = dataSize; } memcpy(HANDLE_DATA(handle), reply, replyLen); /* Make sure resourcePoolPath is NUL terminated. */ v2reply = HANDLE_DATA(handle); v2reply->resourcePoolPath.value[sizeof v2reply->resourcePoolPath.value - 1] = '\0'; ret = VMGUESTLIB_ERROR_SUCCESS; } else if (hostVersion == 3) { VMGuestLibDataV3 *v3reply = (VMGuestLibDataV3 *)reply; size_t dataSize; XDR xdrs; GuestLibV3StatCount count; VMGuestLibStatisticsV3 *v3stats; /* More sanity checks. */ if (v3reply->hdr.version != hostVersion) { Debug("Incorrect data version returned\n"); ret = VMGUESTLIB_ERROR_OTHER; goto done; } if (replyLen < sizeof *v3reply) { Debug("Incorrect data size returned\n"); ret = VMGUESTLIB_ERROR_OTHER; goto done; } /* 0. Copy the reply version and sessionId to the handle. */ HANDLE_VERSION(handle) = v3reply->hdr.version; HANDLE_SESSIONID(handle) = v3reply->hdr.sessionId; /* * 1. Retrieve the length of the statistics array from the XDR encoded * part of the reply. */ xdrmem_create(&xdrs, v3reply->data, v3reply->dataSize, XDR_DECODE); if (!xdr_GuestLibV3StatCount(&xdrs, &count)) { xdr_destroy(&xdrs); goto done; } if (count >= GUESTLIB_MAX_STATISTIC_ID) { /* * Host has more than we can process. So process only what this side * can. */ count = GUESTLIB_MAX_STATISTIC_ID - 1; } /* 2. [Re]alloc if the local handle buffer is not big enough. */ dataSize = sizeof *v3stats + (count * sizeof (GuestLibV3Stat)); if (HANDLE_DATASIZE(handle) < dataSize) { free(HANDLE_DATA(handle)); HANDLE_DATA(handle) = Util_SafeCalloc(1, dataSize); HANDLE_DATASIZE(handle) = dataSize; } /* 3. Unmarshal the array of statistics. */ v3stats = HANDLE_DATA(handle); v3stats->numStats = count; for (count = 0; count < v3stats->numStats; count++) { GuestLibV3TypeIds statId = count + 1; /* Unmarshal the statistic. */ if (!xdr_GuestLibV3Stat(&xdrs, &v3stats->stats[count])) { break; } /* Host sends all the V3 statistics it supports, in order. */ if (v3stats->stats[count].d != statId) { break; } } if (count >= v3stats->numStats) { ret = VMGUESTLIB_ERROR_SUCCESS; } else { /* * Error while unmarshalling. Deep-free already unmarshalled * statistics and invalidate the data in the handle. */ GuestLibV3StatCount c; for (c = 0; c < count; c++) { VMX_XDR_FREE(xdr_GuestLibV3Stat, &v3stats->stats[c]); } HANDLE_SESSIONID(handle) = 0; } /* 4. Free resources. */ xdr_destroy(&xdrs); } else { /* * Host should never reply with a higher version protocol than requested. */ ret = VMGUESTLIB_ERROR_OTHER; } done: free(reply); return ret; }
static int StrUtilStrncmp(const char *s1, const char *s2, size_t n) { return Str_Strncmp(s1, s2, n); }
static Bool ResolutionCanSet(void) { ResolutionInfoX11Type *resInfoX = &resolutionInfoX11; FileIODescriptor fd; FileIOResult res; int64 filePos = 0; Bool keepSearching = TRUE; Bool found = FALSE; char buf[sizeof VERSION_STRING + 10]; // size of VERSION_STRING plus some extra for the version number const char versionString[] = VERSION_STRING; size_t bytesRead; int32 major, minor, level; unsigned int tokPos; /* See if the randr X module is loaded */ if (!XRRQueryVersion(resInfoX->display, &major, &minor) ) { return FALSE; } #ifndef NO_MULTIMON /* * See if RandR >= 1.2 can be used: The extension version is high enough and * all output names match the expected format. */ if (major > 1 || (major == 1 && minor >= 2)) { XRRScreenResources* xrrRes; XRROutputInfo* xrrOutput; unsigned int num; int i; xrrRes = XRRGetScreenResources(resInfoX->display, resInfoX->rootWindow); if (xrrRes) { for (i = 0; i < xrrRes->noutput; i++) { xrrOutput = XRRGetOutputInfo(resInfoX->display, xrrRes, xrrRes->outputs[i]); if (!xrrOutput) { break; } if (sscanf(xrrOutput->name, RR12_OUTPUT_FORMAT, &num) != 1 || num < 1) { XRRFreeOutputInfo(xrrOutput); break; } XRRFreeOutputInfo(xrrOutput); } if (i == xrrRes->noutput) { resInfoX->canUseRandR12 = TRUE; } else { g_debug("RandR >= 1.2 not usable\n"); } XRRFreeScreenResources(xrrRes); } if (resInfoX->canUseRandR12) { return TRUE; } } #endif // ifndef NO_MULTIMON /* * See if the VMWARE_CTRL extension is supported. */ if (resInfoX->canUseVMwareCtrl) { return TRUE; } /* * XXX: This check does not work with XOrg 6.9/7.0 for two reasons: Both * versions now use .so for the driver extension and 7.0 moves the drivers * to a completely different directory. As long as we ship a driver for * 6.9/7.0, we can instead just use the VMWARE_CTRL check. */ buf[sizeof buf - 1] = '\0'; FileIO_Invalidate(&fd); res = FileIO_Open(&fd, VMWAREDRV_PATH_64, FILEIO_ACCESS_READ, FILEIO_OPEN); if (res != FILEIO_SUCCESS) { res = FileIO_Open(&fd, VMWAREDRV_PATH, FILEIO_ACCESS_READ, FILEIO_OPEN); } if (res == FILEIO_SUCCESS) { /* * One of the opens succeeded, so start searching thru the file. */ while (keepSearching) { res = FileIO_Read(&fd, buf, sizeof buf - 1, &bytesRead); if (res != FILEIO_SUCCESS || bytesRead < sizeof buf -1 ) { keepSearching = FALSE; } else { if (Str_Strncmp(versionString, buf, sizeof versionString - 1) == 0) { keepSearching = FALSE; found = TRUE; } } filePos = FileIO_Seek(&fd, filePos+1, FILEIO_SEEK_BEGIN); if (filePos == -1) { keepSearching = FALSE; } } FileIO_Close(&fd); if (found) { /* * We NUL-terminated buf earlier, but Coverity really wants it to * be NUL-terminated after the call to FileIO_Read (because * FileIO_Read doesn't NUL-terminate). So we'll do it again. */ buf[sizeof buf - 1] = '\0'; /* * Try and parse the major, minor and level versions */ tokPos = sizeof versionString - 1; if (!StrUtil_GetNextIntToken(&major, &tokPos, buf, ".- ")) { return FALSE; } if (!StrUtil_GetNextIntToken(&minor, &tokPos, buf, ".- ")) { return FALSE; } if (!StrUtil_GetNextIntToken(&level, &tokPos, buf, ".- ")) { return FALSE; } return ((major > 10) || (major == 10 && minor >= 11)); } } return FALSE; }
void VMTools_BindTextDomain(const char *domain, const char *lang, const char *catdir) { char *dfltdir = NULL; gchar *file; gchar *usrlang = NULL; MsgState *state = MsgGetState(); MsgCatalog *catalog; ASSERT(domain); /* * If the caller has asked for the default user language, detect it and * translate to our internal language string representation. */ if (lang == NULL || *lang == '\0') { usrlang = MsgGetUserLanguage(); lang = usrlang; } g_debug("%s: user locale=%s\n", __FUNCTION__, lang); /* * Use the default install directory if none is provided. */ if (catdir == NULL) { #if defined(OPEN_VM_TOOLS) dfltdir = Util_SafeStrdup(VMTOOLS_DATA_DIR); #else dfltdir = GuestApp_GetInstallPath(); #endif catdir = (dfltdir) ? dfltdir : "."; } file = g_strdup_printf("%s%smessages%s%s%s%s.vmsg", catdir, DIRSEPS, DIRSEPS, lang, DIRSEPS, domain); if (!File_IsFile(file)) { /* * If we couldn't find the catalog file for the user's language, see if * we can find a more generic language (e.g., for "en_US", also try "en"). */ char *sep = Str_Strrchr(lang, '_'); if (sep != NULL) { if (usrlang == NULL) { usrlang = Util_SafeStrdup(lang); } usrlang[sep - lang] = '\0'; g_free(file); file = g_strdup_printf("%s%smessages%s%s%s%s.vmsg", catdir, DIRSEPS, DIRSEPS, usrlang, DIRSEPS, domain); } } catalog = MsgLoadCatalog(file); if (catalog == NULL) { if (Str_Strncmp(lang, "en", 2)) { /* * Don't warn about english dictionary, which may not exist (it is the * default translation). */ g_message("Cannot load message catalog for domain '%s', language '%s', " "catalog dir '%s'.\n", domain, lang, catdir); } } else { g_static_mutex_lock(&state->lock); MsgSetCatalog(domain, catalog); g_static_mutex_unlock(&state->lock); } g_free(file); free(dfltdir); g_free(usrlang); }