char * Unicode_Join(const char *first, // IN: ...) // IN: { char *result; if (first == NULL) { result = NULL; } else { va_list args; const char *cur; result = Unicode_Duplicate(first); va_start(args, first); while ((cur = va_arg(args, const char *)) != NULL) { char *temp; temp = Unicode_Format("%s%s", result, cur); free(result); result = temp; } va_end(args); } return result; }
static Unicode FileMakeTempExCreateNameFunc(uint32 num, // IN: void *data) // IN: { if (data == NULL) { return NULL; } return Unicode_Format("%s%u", (Unicode) data, num); }
Unicode System_GetTimeAsString(void) { struct timeval tv; time_t sec; int msec; size_t charsWritten; size_t bufSize = 8; // Multiplied by 2 for the initial allocation. char *buf = NULL; Unicode dateTime = NULL; Unicode output = NULL; if (gettimeofday(&tv, NULL)) { goto out; } sec = tv.tv_sec; msec = tv.tv_usec / 1000; /* * Loop repeatedly trying to format the time into a buffer, doubling the * buffer with each failure. This should be safe as the manpage for * strftime(3) seems to suggest that it only fails if the buffer isn't large * enough. * * The resultant string is encoded according to the current locale. */ do { char *newBuf; bufSize *= 2; newBuf = realloc(buf, bufSize); if (newBuf == NULL) { goto out; } buf = newBuf; charsWritten = strftime(buf, bufSize, "%b %d %H:%M:%S", localtime(&sec)); } while (charsWritten == 0); /* * Append the milliseconds field, but only after converting the date/time * string from encoding specified in the current locale to an opaque type. */ dateTime = Unicode_Alloc(buf, STRING_ENCODING_DEFAULT); if (dateTime == NULL) { goto out; } output = Unicode_Format("%s.%03d", dateTime, msec); out: free(buf); Unicode_Free(dateTime); return output; }
static char * FileFindExistingSafeTmpDir(uid_t userId, // IN: const char *userName, // IN: const char *baseTmpDir) // IN: { int i; int numFiles; char *pattern; char *tmpDir = NULL; char **fileList = NULL; /* * We always use the pattern PRODUCT-USER-xxxx when creating * alternative safe temp directories, so check for ones with * those names and the appropriate permissions. */ pattern = Unicode_Format("%s-%s-", PRODUCT_GENERIC_NAME_LOWER, userName); if (pattern == NULL) { return NULL; } numFiles = File_ListDirectory(baseTmpDir, &fileList); if (numFiles == -1) { free(pattern); return NULL; } for (i = 0; i < numFiles; i++) { if (Unicode_StartsWith(fileList[i], pattern)) { char *path = Unicode_Join(baseTmpDir, DIRSEPS, fileList[i], NULL); if (File_IsDirectory(path) && FileAcceptableSafeTmpDir(path, userId)) { tmpDir = path; break; } free(path); } } Util_FreeStringList(fileList, numFiles); free(pattern); return tmpDir; }
char * DnD_CreateStagingDirectory(void) { const char *root; char **stagingDirList; int numStagingDirs; int i; char *ret = NULL; Bool found = FALSE; /* * Make sure the root staging directory is created with the correct * permissions. */ root = DnDCreateRootStagingDirectory(); if (!root) { return NULL; } /* Look for an existing, empty staging directory */ numStagingDirs = File_ListDirectory(root, &stagingDirList); if (numStagingDirs < 0) { goto exit; } for (i = 0; i < numStagingDirs; i++) { if (!found) { char *stagingDir; stagingDir = Unicode_Append(root, stagingDirList[i]); if (File_IsEmptyDirectory(stagingDir) && DnDStagingDirectoryUsable(stagingDir)) { ret = Unicode_Append(stagingDir, DIRSEPS); /* * We can use this directory. Make sure to continue to loop * so we don't leak the remaining stagindDirList[i]s. */ found = TRUE; } free(stagingDir); } } Util_FreeStringList(stagingDirList, numStagingDirs); /* Only create a directory if we didn't find one above. */ if (!found) { rqContext *context; context = Random_QuickSeed((unsigned)time(NULL)); for (i = 0; i < 10; i++) { char *temp; /* Each staging directory is given a random name. */ free(ret); temp = Unicode_Format("%08x%c", Random_Quick(context), DIRSEPC); VERIFY(temp); ret = Unicode_Append(root, temp); free(temp); if (File_CreateDirectory(ret) && DnDSetPermissionsOnStagingDir(ret)) { found = TRUE; break; } } free(context); } exit: if (!found && ret != NULL) { free(ret); ret = NULL; } return ret; }
static int CreateEntryDirectory(const char *machineID, // IN: const char *executionID, // IN: ConstUnicode lockDir, // IN: Unicode *entryDirectory, // OUT: Unicode *entryFilePath, // OUT: Unicode *memberFilePath, // OUT: Unicode *memberName) // OUT: { int err = 0; uint32 randomNumber = 0; ASSERT(lockDir); *entryDirectory = NULL; *entryFilePath = NULL; *memberFilePath = NULL; *memberName = NULL; /* Fun at the races */ while (TRUE) { Unicode temp; FileData fileData; err = FileAttributesRobust(lockDir, &fileData); if (err == 0) { /* The name exists. Deal with it... */ if (fileData.fileType == FILE_TYPE_REGULAR) { /* * It's a file. Assume this is an (active?) old style lock and * err on the safe side - don't remove it (and automatically * upgrade to a new style lock). */ Log(LGPFX" %s: '%s' exists; an old style lock file?\n", __FUNCTION__, UTF8(lockDir)); err = EAGAIN; break; } if (fileData.fileType != FILE_TYPE_DIRECTORY) { /* Not a directory; attempt to remove the debris */ if (FileDeletionRobust(lockDir, FALSE) != 0) { Warning(LGPFX" %s: '%s' exists and is not a directory.\n", __FUNCTION__, UTF8(lockDir)); err = ENOTDIR; break; } continue; } } else { if (err == ENOENT) { /* Not there anymore; locker unlocked or timed out */ err = MakeDirectory(lockDir); if ((err != 0) && (err != EEXIST)) { Warning(LGPFX" %s creation failure on '%s': %s\n", __FUNCTION__, UTF8(lockDir), strerror(err)); break; } } else { Warning(LGPFX" %s stat failure on '%s': %s\n", __FUNCTION__, UTF8(lockDir), strerror(err)); break; } } /* There is a small chance of collision/failure; grab stings now */ randomNumber = SimpleRandomNumber(machineID, executionID); *memberName = Unicode_Format("M%05u%s", randomNumber, FILELOCK_SUFFIX); temp = Unicode_Format("D%05u%s", randomNumber, FILELOCK_SUFFIX); *entryDirectory = Unicode_Join(lockDir, DIRSEPS, temp, NULL); Unicode_Free(temp); temp = Unicode_Format("E%05u%s", randomNumber, FILELOCK_SUFFIX); *entryFilePath = Unicode_Join(lockDir, DIRSEPS, temp, NULL); Unicode_Free(temp); *memberFilePath = Unicode_Join(lockDir, DIRSEPS, *memberName, NULL); err = MakeDirectory(*entryDirectory); if (err == 0) { /* * The entry directory was safely created. See if a member file * is in use (the entry directory is removed once the member file * is created). If a member file is in use, choose another number, * otherwise the use of the this number is OK. * * Err on the side of caution... don't want to trash perfectly * good member files. */ err = FileAttributesRobust(*memberFilePath, NULL); if (err != 0) { if (err == ENOENT) { err = 0; break; } if (vmx86_debug) { Log(LGPFX" %s stat failure on '%s': %s\n", __FUNCTION__, UTF8(*memberFilePath), strerror(err)); } } FileRemoveDirectoryRobust(*entryDirectory); } else { if ((err != EEXIST) && // Another process/thread created it... (err != ENOENT)) { // lockDir is gone... Warning(LGPFX" %s creation failure on '%s': %s\n", __FUNCTION__, UTF8(*entryDirectory), strerror(err)); break; } } Unicode_Free(*entryDirectory); Unicode_Free(*entryFilePath); Unicode_Free(*memberFilePath); Unicode_Free(*memberName); *entryDirectory = NULL; *entryFilePath = NULL; *memberFilePath = NULL; *memberName = NULL; } if (err != 0) { Unicode_Free(*entryDirectory); Unicode_Free(*entryFilePath); Unicode_Free(*memberFilePath); Unicode_Free(*memberName); *entryDirectory = NULL; *entryFilePath = NULL; *memberFilePath = NULL; *memberName = NULL; } return err; }