char * StrUtil_AppendListItem(char const *list, // IN: char delim, // IN: char const *item) // IN: { if (list == NULL) { return Str_Asprintf(NULL, "%s", item); } else { return Str_Asprintf(NULL, "%s%c%s", list, delim, item); } }
char * URL_Get(UrlId id, // IN Bool append) // IN: Allow things to be appended { unsigned int index; char *result; if (id == 0) { /* Invalid ID --hpreg */ return NULL; } /* Lookup the URLs array for a URL ID --hpreg */ for (index = 0; index < sizeof(URLs) / sizeof(URLs[0]); index++) { if (URLs[index].id == id) { break; } } if (index == sizeof(URLs) / sizeof(URLs[0])) { /* Invalid ID --hpreg */ return NULL; } result = Str_Asprintf(NULL, "http://%s.com/info?id=%u", PRODUCT_GENERIC_NAME_LOWER, URLs[index].id); if (result == NULL) { return NULL; } if (append) { unsigned int i; for (i = 0; i < sizeof(appends) / sizeof(appends[0]); i++) { if ((URLs[index].appends & (1 << i)) && appends[i].value) { char *tmpResult; char encName[1024]; char encValue[1024]; URL_EncodeURL(appends[i].name, encName, sizeof(encName)); URL_EncodeURL(appends[i].value, encValue, sizeof(encValue)); tmpResult = Str_Asprintf(NULL, "%1$s&%2$s=%3$s", result, encName, encValue); free(result); if (tmpResult == NULL) { return NULL; } result = tmpResult; } } } return result; }
char * TimeUtil_GetTimeFormat(int64 utcTime, // IN Bool showDate, // IN Bool showTime) // IN { #ifdef _WIN32 SYSTEMTIME systemTime = { 0 }; char dateStr[100] = ""; char timeStr[100] = ""; if (!showDate && !showTime) { return NULL; } if (!TimeUtil_UTCTimeToSystemTime((const __time64_t) utcTime, &systemTime)) { return NULL; } Win32U_GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &systemTime, NULL, dateStr, ARRAYSIZE(dateStr)); Win32U_GetTimeFormat(LOCALE_USER_DEFAULT, 0, &systemTime, NULL, timeStr, ARRAYSIZE(timeStr)); if (showDate && showTime) { return Str_Asprintf(NULL, "%s %s", dateStr, timeStr); } else { return Str_Asprintf(NULL, "%s", showDate ? dateStr : timeStr); } #else /* * On 32-bit systems the assignment of utcTime to time_t below will truncate * in the year 2038. Ignore it; there's nothing we can do. */ char *str; char buf[26]; const time_t t = (time_t) utcTime; // Implicit narrowing on 32-bit #if defined sun str = Util_SafeStrdup(ctime_r(&t, buf, sizeof buf)); #else str = Util_SafeStrdup(ctime_r(&t, buf)); #endif str[strlen(str) - 1] = '\0'; // Remove the trailing '\n'. return str; #endif // _WIN32 }
void AppUtil_SendGuestCaps(const GuestCapabilities *caps, // IN: array of capabilities size_t numCaps, // IN: number of capabilities Bool enabled) // IN: capabilities status { char *capsStr = NULL; char *capsTemp = NULL; size_t capIdx; ASSERT(caps); ASSERT(numCaps > 0); capsStr = strdup(GUEST_CAP_FEATURES); for (capIdx = 0; capIdx < numCaps; capIdx++) { if (!capsStr) { Debug("%s: Not enough memory to create capabilities string\n", __FUNCTION__); return; } capsTemp = Str_Asprintf(NULL, "%s %d=%d", capsStr, caps[capIdx], (int)enabled); free(capsStr); capsStr = capsTemp; } if (!RpcOut_sendOne(NULL, NULL, capsStr)) { Debug("%s: could not set capabilities: older vmx?\n", __FUNCTION__); } free(capsStr); }
char * GuestApp_GetInstallPath(void) { char *pathUtf8 = NULL; #if defined(_WIN32) size_t pathLen = 0; if (WinReg_GetSZ(HKEY_LOCAL_MACHINE, CONF_VMWARE_TOOLS_REGKEY, "InstallPath", &pathUtf8) != ERROR_SUCCESS) { Warning("%s: Unable to retrieve install path: %s\n", __FUNCTION__, Msg_ErrString()); return NULL; } /* Strip off the trailing backslash, if present */ pathLen = strlen(pathUtf8); if (pathLen > 0) { if (pathUtf8[pathLen - 1] == '\\') { pathUtf8[pathLen - 1] = '\0'; } } #else pathUtf8 = Str_Asprintf(NULL, "%s", GUESTAPP_TOOLS_INSTALL_PATH); #endif return pathUtf8; }
static char * VmBackupGetScriptPath(void) { char *scriptPath = NULL; char *installPath = GuestApp_GetInstallPath(); if (installPath == NULL) { return NULL; } scriptPath = Str_Asprintf(NULL, "%s%s%s", installPath, DIRSEPS, "backupScripts.d"); free(installPath); return scriptPath; }
char * HgfsUri_ConvertFromPathToHgfsUri(const char *pathName, // IN: path to convert Bool hgfsOnly) // IN { char *shareUri = NULL; Bool isHgfsName = FALSE; char *sharesDefaultRootPath = NULL; /* We can only operate on full paths. */ if (pathName[0] != DIRSEPC) { return shareUri; } /* Retrieve the servername & share name in use. */ if (!HgfsHlpr_QuerySharesDefaultRootPath(&sharesDefaultRootPath)) { Debug("%s: Unable to query shares default root path\n", __FUNCTION__); goto exit; } if (Unicode_StartsWith(pathName, sharesDefaultRootPath)) { char *relativeSharePath = NULL; char *escapedSharePath = NULL; UnicodeIndex relativePathStart = strlen(sharesDefaultRootPath); if ( strlen(pathName) > relativePathStart && pathName[relativePathStart] == DIRSEPC) { relativePathStart++; } relativeSharePath = Unicode_RemoveRange(pathName, 0, relativePathStart); HgfsEscape_Undo(relativeSharePath, strlen(relativeSharePath) + 1); escapedSharePath = g_uri_escape_string(relativeSharePath, "/", FALSE); shareUri = Unicode_Append(GHI_HGFS_SHARE_URL_UTF8, escapedSharePath); g_free(escapedSharePath); free(relativeSharePath); isHgfsName = TRUE; } exit: if (!isHgfsName && !hgfsOnly) { /* Only convert non-hgfs file name if hgfsOnly is not set. */ char *escapedPath = g_uri_escape_string(pathName, "/", FALSE); shareUri = Str_Asprintf(NULL, "file://%s", escapedPath); g_free(escapedPath); } HgfsHlpr_FreeSharesRootPath(sharesDefaultRootPath); return shareUri; }
static gboolean RpcChannelReset(RpcInData *data) { gchar *msg; RpcChannelInt *chan = data->clientData; if (chan->resetCheck == NULL) { chan->resetCheck = g_idle_source_new(); g_source_set_priority(chan->resetCheck, G_PRIORITY_HIGH); g_source_set_callback(chan->resetCheck, RpcChannelCheckReset, chan, NULL); g_source_attach(chan->resetCheck, chan->mainCtx); } msg = Str_Asprintf(NULL, "ATR %s", chan->appName); ASSERT_MEM_ALLOC(msg); return RPCIN_SETRETVALSF(data, msg, TRUE); }
const char * Xdg_GetCacheHome(void) { static char *result = NULL; struct passwd *pw; if (result == NULL) { do { if (!Id_IsSetUGid()) { const char *base = NULL; /* * Paranoia: Avoid environment variables if running in a sensitive * context. sudo or other loader should've sanitized the * environment, but, well, we're paranoid, remember? */ // 1. $XDG_CACHE_HOME base = Posix_Getenv("XDG_CACHE_HOME"); if (Util_IsAbsolutePath(base)) { result = Util_SafeStrdup(base); break; } // 2. $HOME/.cache base = Posix_Getenv("HOME"); if (Util_IsAbsolutePath(base)) { result = Util_SafeStrdup(base); StrUtil_SafeStrcat(&result, "/.cache"); break; } } // 3. <pw_dir>/.cache pw = Posix_Getpwuid(geteuid()); if (pw != NULL && Util_IsAbsolutePath(pw->pw_dir)) { result = Str_Asprintf(NULL, "%s/.cache", pw->pw_dir); } } while(0); } VERIFY(result == NULL || result[0] == '/'); return result; }
static char * FileCreateSafeTmpDir(uid_t userId, // IN: const char *userName, // IN: const char *baseTmpDir) // IN: { static const int MAX_DIR_ITERS = 250; int curDirIter = 0; char *tmpDir = NULL; while (TRUE) { /* * We use a random number that makes it more likely that we will create * an unused name than if we had simply tried suffixes in numeric order. */ tmpDir = Str_Asprintf(NULL, "%s%s%s-%s-%u", baseTmpDir, DIRSEPS, PRODUCT_GENERIC_NAME_LOWER, userName, FileSimpleRandom()); if (!tmpDir) { Warning("%s: Out of memory error.\n", __FUNCTION__); break; } if (FileAcceptableSafeTmpDir(tmpDir, userId)) { break; } if (++curDirIter > MAX_DIR_ITERS) { Warning("%s: Failed to create a safe temporary directory, path " "\"%s\". The maximum number of attempts was exceeded.\n", __FUNCTION__, tmpDir); free(tmpDir); tmpDir = NULL; break; } free(tmpDir); tmpDir = NULL; } return tmpDir; }
static void UpdateMtab(HgfsMountInfo *mountInfo, // IN: Info to write into mtab int flags) // IN: Flags (read-only, etc.) { struct mntent mountEnt; FILE *mountFile; struct passwd *password; char *userName = NULL; ASSERT(mountInfo); mountFile = setmntent(MOUNTED, "a+"); if (mountFile == NULL) { printf("Could not open mtab for appending, continuing sans mtab\n"); return; } /* We only care about the mounting user if it isn't root. */ if (getuid() != 0) { password = getpwuid(getuid()); if (password == NULL) { printf("Could not get user for mounting uid, skipping user entry\n"); } else { userName = password->pw_name; } } /* * Create the mtab entry to be written. We'll go ahead and try to write * even if we fail to allocate the mount options. */ mountEnt.mnt_fsname = shareName; mountEnt.mnt_dir = mountPoint; mountEnt.mnt_type = HGFS_NAME; mountEnt.mnt_freq = 0; mountEnt.mnt_passno = 0; mountEnt.mnt_opts = malloc(MOUNT_OPTS_BUFFER_SIZE); if (mountEnt.mnt_opts) { char *ttlString; memset(mountEnt.mnt_opts, 0, MOUNT_OPTS_BUFFER_SIZE); /* * These are typically the displayed options in /etc/mtab (note that not * all options are typically displayed, just those the user may find * interesting). */ if (flags & MS_RDONLY) { Str_Strcat(mountEnt.mnt_opts, "ro", MOUNT_OPTS_BUFFER_SIZE); } else { Str_Strcat(mountEnt.mnt_opts, "rw", MOUNT_OPTS_BUFFER_SIZE); } if (flags & MS_NOSUID) { Str_Strcat(mountEnt.mnt_opts, ",nosuid", MOUNT_OPTS_BUFFER_SIZE); } #ifdef MS_NODEV if (flags & MS_NODEV) { Str_Strcat(mountEnt.mnt_opts, ",nodev", MOUNT_OPTS_BUFFER_SIZE); } #endif if (flags & MS_NOEXEC) { Str_Strcat(mountEnt.mnt_opts, ",noexec", MOUNT_OPTS_BUFFER_SIZE); } if (flags & MS_SYNCHRONOUS) { Str_Strcat(mountEnt.mnt_opts, ",sync", MOUNT_OPTS_BUFFER_SIZE); } if (flags & MS_MANDLOCK) { Str_Strcat(mountEnt.mnt_opts, ",mand", MOUNT_OPTS_BUFFER_SIZE); } if (flags & MS_NOATIME) { Str_Strcat(mountEnt.mnt_opts, ",noatime", MOUNT_OPTS_BUFFER_SIZE); } if (flags & MS_NODIRATIME) { Str_Strcat(mountEnt.mnt_opts, ",nodiratime", MOUNT_OPTS_BUFFER_SIZE); } if (userName != NULL) { Str_Strcat(mountEnt.mnt_opts, ",user="******"%u", mountInfo->ttl); if (ttlString != NULL) { Str_Strcat(mountEnt.mnt_opts, ",ttl=", MOUNT_OPTS_BUFFER_SIZE); Str_Strcat(mountEnt.mnt_opts, ttlString, MOUNT_OPTS_BUFFER_SIZE); free(ttlString); } else { printf("Could not allocate memory for ttl entry in mtab, " "continuing\n"); } } /* Add the entry and close. */ if (addmntent(mountFile, &mountEnt)) { printf("Could not add entry to mtab, continuing\n"); } endmntent(mountFile); if (mountEnt.mnt_opts) { free(mountEnt.mnt_opts); } }
char * StrUtil_FormatSizeInBytesUnlocalized(uint64 size) // IN { /* * XXX TODO, BUG 199661: * This is a direct copy of Msg_FormatSizeInBytes without localization. * These two functions should ideally share the basic functionality, and * just differ in the string localization */ char const *fmt; double sizeInSelectedUnit; unsigned int precision; char *sizeFormat; char *sizeString; char *result; static const double epsilon = 0.01; double delta; if (size >= CONST64U(1) << 40 /* 1 TB */) { fmt = "%s TB"; sizeInSelectedUnit = (double)size / (CONST64U(1) << 40); precision = 1; } else if (size >= CONST64U(1) << 30 /* 1 GB */) { fmt = "%s GB"; sizeInSelectedUnit = (double)size / (CONST64U(1) << 30); precision = 1; } else if (size >= CONST64U(1) << 20 /* 1 MB */) { fmt = "%s MB"; sizeInSelectedUnit = (double)size / (CONST64U(1) << 20); precision = 1; } else if (size >= CONST64U(1) << 10 /* 1 KB */) { fmt = "%s KB"; sizeInSelectedUnit = (double)size / (CONST64U(1) << 10); precision = 1; } else if (size >= CONST64U(2) /* 2 bytes */) { fmt = "%s bytes"; sizeInSelectedUnit = (double)size; precision = 0; // No fractional byte. } else if (size >= CONST64U(1) /* 1 byte */) { fmt = "%s byte"; sizeInSelectedUnit = (double)size; precision = 0; // No fractional byte. } else { ASSERT(size == CONST64U(0) /* 0 bytes */); fmt = "%s bytes"; sizeInSelectedUnit = (double)size; precision = 0; // No fractional byte. } /* * We cast to uint32 instead of uint64 here because of a problem with the * NetWare Tools build. However, it's safe to cast to uint32 since we have * already reduced the range of sizeInSelectedUnit above. */ // If it would display with .0, round it off and display the integer value. delta = (uint32)(sizeInSelectedUnit + 0.5) - sizeInSelectedUnit; if (delta < 0) { delta = -delta; } if (delta <= epsilon) { precision = 0; sizeInSelectedUnit = (double)(uint32)(sizeInSelectedUnit + 0.5); } sizeFormat = Str_Asprintf(NULL, "%%.%uf", precision); sizeString = Str_Asprintf(NULL, sizeFormat, sizeInSelectedUnit); result = Str_Asprintf(NULL, fmt, sizeString); free(sizeFormat); free(sizeString); return result; }
static int VmBackupRunNextScript(VmBackupScriptOp *op) // IN/OUT { const char *scriptOp; int ret = 0; ssize_t index; VmBackupScript *scripts = op->state->scripts; switch (op->type) { case VMBACKUP_SCRIPT_FREEZE: index = ++op->state->currentScript; scriptOp = "freeze"; break; case VMBACKUP_SCRIPT_FREEZE_FAIL: index = --op->state->currentScript; scriptOp = "freezeFail"; break; case VMBACKUP_SCRIPT_THAW: index = --op->state->currentScript; scriptOp = "thaw"; break; default: NOT_REACHED(); } while (index >= 0 && scripts[index].path != NULL) { char *cmd; if (File_IsFile(scripts[index].path)) { if (op->state->scriptArg != NULL) { cmd = Str_Asprintf(NULL, "\"%s\" %s \"%s\"", scripts[index].path, scriptOp, op->state->scriptArg); } else { cmd = Str_Asprintf(NULL, "\"%s\" %s", scripts[index].path, scriptOp); } if (cmd != NULL) { g_debug("Running script: %s\n", cmd); scripts[index].proc = ProcMgr_ExecAsync(cmd, NULL); } else { g_debug("Failed to allocate memory to run script: %s\n", scripts[index].path); scripts[index].proc = NULL; } vm_free(cmd); if (scripts[index].proc == NULL) { if (op->type == VMBACKUP_SCRIPT_FREEZE) { ret = -1; break; } else { op->thawFailed = TRUE; } } else { ret = 1; break; } } if (op->type == VMBACKUP_SCRIPT_FREEZE) { index = ++op->state->currentScript; } else { index = --op->state->currentScript; } /* * This happens if all thaw/fail scripts failed to start. Since the first * entry may be a legacy script (which may not exist), need to check * whether the interesting failure is the first or the second entry in * the script list. */ if (index == -1) { size_t failIdx = 0; if (!File_IsFile(scripts[0].path)) { failIdx = 1; } if (scripts[failIdx].proc == NULL && scripts[failIdx].path != NULL) { ret = -1; } } } return ret; }
VmBackupOp * VmBackup_NewScriptOp(VmBackupScriptType type, // IN VmBackupState *state) // IN { Bool fail = FALSE; char **fileList = NULL; char *scriptDir = NULL; int numFiles = 0; size_t i; VmBackupScriptOp *op = NULL; scriptDir = VmBackupGetScriptPath(); if (scriptDir == NULL) { goto exit; } op = calloc(1, sizeof *op); if (op == NULL) { goto exit; } op->state = state; op->type = type; op->callbacks.queryFn = VmBackupScriptOpQuery; op->callbacks.cancelFn = VmBackupScriptOpCancel; op->callbacks.releaseFn = VmBackupScriptOpRelease; g_debug("Trying to run scripts from %s\n", scriptDir); /* * Load the list of scripts to run when freezing. The same list will be * used later in case of failure, or when thawing, in reverse order. * * This logic won't recurse into directories, so only files directly under * the script dir will be considered. * * Legacy scripts will be the first ones to run (or last ones in the * case of thawing). If either the legacy freeze or thaw script * exist, the first entry in the script list will be reserved for * them, and their path might not exist (in case, for example, the * freeze script exists but the thaw script doesn't). */ if (type == VMBACKUP_SCRIPT_FREEZE) { VmBackupScript *scripts = NULL; int legacy = 0; size_t idx = 0; state->scripts = NULL; state->currentScript = 0; if (File_IsFile(LEGACY_FREEZE_SCRIPT) || File_IsFile(LEGACY_THAW_SCRIPT)) { legacy = 1; } if (File_IsDirectory(scriptDir)) { numFiles = File_ListDirectory(scriptDir, &fileList); } if (numFiles + legacy > 0) { scripts = calloc(numFiles + legacy + 1, sizeof *scripts); if (scripts == NULL) { fail = TRUE; goto exit; } /* * VmBackupRunNextScript increments the index, so need to make it point * to "before the first script". */ state->currentScript = -1; state->scripts = scripts; } if (legacy > 0) { scripts[idx++].path = Util_SafeStrdup(LEGACY_FREEZE_SCRIPT); } if (numFiles > 0) { size_t i; if (numFiles > 1) { qsort(fileList, (size_t) numFiles, sizeof *fileList, VmBackupStringCompare); } for (i = 0; i < numFiles; i++) { char *script; script = Str_Asprintf(NULL, "%s%c%s", scriptDir, DIRSEPC, fileList[i]); if (script == NULL) { fail = TRUE; goto exit; } else if (File_IsFile(script)) { scripts[idx++].path = script; } else { free(script); } } } } else if (state->scripts != NULL) { VmBackupScript *scripts = state->scripts; if (strcmp(scripts[0].path, LEGACY_FREEZE_SCRIPT) == 0) { vm_free(scripts[0].path); scripts[0].path = Util_SafeStrdup(LEGACY_THAW_SCRIPT); } } /* * If there are any scripts to be executed, start the first one. If we get to * this point, we won't free the scripts array until VmBackupScriptOpRelease * is called after thawing (or after the sync provider failed and the "fail" * scripts are run). */ fail = (state->scripts != NULL && VmBackupRunNextScript(op) == -1); exit: /* Free the file list. */ for (i = 0; i < numFiles; i++) { free(fileList[i]); } free(fileList); if (fail && op != NULL) { VmBackup_Release((VmBackupOp *) op); op = NULL; } free(scriptDir); return (VmBackupOp *) op; }
/* *---------------------------------------------------------------------- * * SysCompatIsInstalledFuse * * Test if the FUSE file system is installed but not yet loaded. * * Results: * FALSE the HGFS FUSE client is not installed, TRUE if it is installed. * * Side effects: * None * *---------------------------------------------------------------------- */ static Bool SysCompatIsInstalledFuse(char *utsRelease) // IN: kernel release { char *fuseFilesystem; char *modulesDep; char *modulesDepData = NULL; struct stat modulesDepStat; size_t modulesDepLen; size_t modulesDepDataSize; size_t modulesDepFileSize; int modulesDepFd = -1; Bool installedFuse = FALSE; int statResult; modulesDep = Str_Asprintf(&modulesDepLen, "%s/%s/%s", LIB_MODULEPATH, utsRelease, MODULES_DEP); if (modulesDep == NULL) { fprintf(stderr, "failed to create path str for %s\n", MODULES_DEP); goto exit; } modulesDepFd = open(modulesDep, O_RDONLY); if (modulesDepFd == -1) { fprintf(stderr, "failed to open %s %d\n", modulesDep, errno); goto exit; } statResult = fstat(modulesDepFd, &modulesDepStat); if (statResult == -1) { fprintf(stderr, "failed to stat %s %d\n", modulesDep, errno); goto exit; } modulesDepFileSize = (size_t)modulesDepStat.st_size; modulesDepData = malloc(modulesDepFileSize + 1); if (modulesDepData == NULL) { fprintf(stderr, "failed to alloc data buf for %s\n", modulesDep); goto exit; } modulesDepDataSize = read(modulesDepFd, modulesDepData, modulesDepFileSize); if (modulesDepDataSize != modulesDepFileSize) { fprintf(stderr, "failed to read %s %d\n", modulesDep, errno); goto exit; } modulesDepData[modulesDepDataSize] = '\0'; fuseFilesystem = strstr(modulesDepData, FUSER_KERNEL_FS); installedFuse = (fuseFilesystem != NULL); exit: if (modulesDepFd != -1) { close(modulesDepFd); } free(modulesDepData); free(modulesDep); return installedFuse; }
char * File_GetSafeTmpDir(Bool useConf) // IN: { char *tmpDir; #if defined(__FreeBSD__) || defined(sun) tmpDir = FileGetTmpDir(useConf); #else static Atomic_Ptr lckStorage; static char *safeDir; char *baseTmpDir = NULL; char *userName = NULL; uid_t userId; MXUserExclLock *lck; userId = geteuid(); /* Get and take lock for our safe dir. */ lck = MXUser_CreateSingletonExclLock(&lckStorage, "getSafeTmpDirLock", RANK_getSafeTmpDirLock); VERIFY(lck != NULL); MXUser_AcquireExclLock(lck); /* * Check if we've created a temporary dir already and if it is still usable. */ tmpDir = NULL; if (safeDir && FileAcceptableSafeTmpDir(safeDir, userId)) { tmpDir = Util_SafeStrdup(safeDir); goto exit; } /* We don't have a useable temporary dir, create one. */ baseTmpDir = FileGetTmpDir(useConf); if (!baseTmpDir) { Warning("%s: FileGetTmpDir failed.\n", __FUNCTION__); goto exit; } userName = FileGetUserName(userId); if (!userName) { Warning("%s: FileGetUserName failed, using numeric ID " "as username instead.\n", __FUNCTION__); /* Fallback on just using the userId as the username. */ userName = Str_Asprintf(NULL, "uid-%d", userId); if (!userName) { Warning("%s: Str_Asprintf error.\n", __FUNCTION__); goto exit; } } tmpDir = Str_Asprintf(NULL, "%s%s%s-%s", baseTmpDir, DIRSEPS, PRODUCT_GENERIC_NAME_LOWER, userName); if (!tmpDir) { Warning("%s: Out of memory error.\n", __FUNCTION__); goto exit; } if (!FileAcceptableSafeTmpDir(tmpDir, userId)) { /* * We didn't get our first choice for the safe temp directory. * Search through the unsafe tmp directory to see if there is * an acceptable one to use. */ free(tmpDir); tmpDir = FileFindExistingSafeTmpDir(userId, userName, baseTmpDir); if (!tmpDir) { /* * We didn't find any usable directories, so try to create one now. */ tmpDir = FileCreateSafeTmpDir(userId, userName, baseTmpDir); } } if (tmpDir) { /* * We have successfully created a temporary directory, remember it for * future calls. */ free(safeDir); safeDir = Util_SafeStrdup(tmpDir); } exit: MXUser_ReleaseExclLock(lck); free(baseTmpDir); free(userName); #endif return tmpDir; }
gboolean RpcChannel_SendOne(char **reply, size_t *repLen, char const *reqFmt, ...) { va_list args; gboolean status; char *request; size_t reqLen = 0; status = FALSE; /* Format the request string */ va_start(args, reqFmt); request = Str_Vasprintf(&reqLen, reqFmt, args); va_end(args); /* * If Str_Vasprintf failed, write NULL into the reply if the caller wanted * a reply back. */ if (request == NULL) { goto error; } /* * If the command doesn't contain a space, add one to the end to maintain * compatibility with old VMXs. * * For a long time, the GuestRpc logic in the VMX was wired to expect a * trailing space in every command, even commands without arguments. That is * no longer true, but we must continue to add a trailing space because we * don't know whether we're talking to an old or new VMX. */ if (request[reqLen - 1] != ' ') { char *tmp; tmp = Str_Asprintf(NULL, "%s ", request); free(request); request = tmp; /* * If Str_Asprintf failed, write NULL into reply if the caller wanted * a reply back. */ if (request == NULL) { goto error; } } status = RpcChannel_SendOneRaw(request, reqLen, reply, repLen); free(request); return status; error: if (reply) { *reply = NULL; } if (repLen) { *repLen = 0; } return FALSE; }
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; }
Bool RpcOut_sendOne(char **reply, // OUT: Result size_t *repLen, // OUT: Length of the result char const *reqFmt, // IN: RPCI command ...) // Unspecified { va_list args; Bool status; char *request; size_t reqLen = 0; status = FALSE; /* Format the request string */ va_start(args, reqFmt); request = Str_Vasprintf(&reqLen, reqFmt, args); va_end(args); /* * If Str_Vasprintf failed, write NULL into the reply if the caller wanted * a reply back. */ if (request == NULL) { if (reply) { *reply = NULL; } return FALSE; } /* * If the command doesn't contain a space, add one to the end to maintain * compatibility with old VMXs. * * For a long time, the GuestRpc logic in the VMX was wired to expect a * trailing space in every command, even commands without arguments. That is * no longer true, but we must continue to add a trailing space because we * don't know whether we're talking to an old or new VMX. */ if (strchr(request, ' ') == NULL) { char *tmp; tmp = Str_Asprintf(NULL, "%s ", request); free(request); request = tmp; /* * If Str_Asprintf failed, write NULL into reply if the caller wanted * a reply back. */ if (request == NULL) { if (reply != NULL) { *reply = NULL; } return FALSE; } } status = RpcOut_SendOneRaw(request, reqLen, reply, repLen); free(request); return status; }