static int ActivateLockList(ConstUnicode dirName, // IN: LockValues *myValues) // IN: { ActiveLock *ptr; ASSERT(dirName); ASSERT(Unicode_StartsWith(dirName, "D")); /* Search the list for a matching entry */ for (ptr = myValues->lockList; ptr != NULL; ptr = ptr->next) { if (Unicode_Compare(ptr->dirName, dirName) == 0) { break; } } /* No entry? Attempt to add one. */ if (ptr == NULL) { ptr = Util_SafeMalloc(sizeof *ptr); ptr->next = myValues->lockList; myValues->lockList = ptr; ptr->age = 0; ptr->dirName = Unicode_Duplicate(dirName); } /* Mark the entry (exists) */ ptr->marked = TRUE; return 0; }
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 * 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; }
Bool FileLockIsLocked(ConstUnicode pathName, // IN: int *err) // OUT: { uint32 i; int errValue; int numEntries; Unicode lockDir; Bool isLocked = FALSE; Unicode *fileList = NULL; lockDir = Unicode_Append(pathName, FILELOCK_SUFFIX); numEntries = FileListDirectoryRobust(lockDir, &fileList); if (numEntries == -1) { errValue = errno; goto bail; } for (i = 0; i < numEntries; i++) { if (Unicode_StartsWith(fileList[i], "M")) { isLocked = TRUE; break; } } for (i = 0; i < numEntries; i++) { Unicode_Free(fileList[i]); } free(fileList); errValue = 0; bail: Unicode_Free(lockDir); if (err != NULL) { *err = errValue; } return isLocked; }
Unicode File_ReplaceExtension(ConstUnicode pathName, // IN: ConstUnicode newExtension, // IN: uint32 numExtensions, // IN: ...) // IN: { Unicode path; Unicode base; Unicode result; va_list arguments; UnicodeIndex index; ASSERT(pathName); ASSERT(newExtension); ASSERT(Unicode_StartsWith(newExtension, ".")); File_GetPathName(pathName, &path, &base); index = Unicode_FindLast(base, "."); if (index != UNICODE_INDEX_NOT_FOUND) { Unicode oldBase = base; if (numExtensions) { uint32 i; /* * Only truncate the old extension from the base if it exists in * in the valid extensions list. */ va_start(arguments, numExtensions); for (i = 0; i < numExtensions ; i++) { Unicode oldExtension = va_arg(arguments, Unicode); ASSERT(Unicode_StartsWith(oldExtension, ".")); if (Unicode_CompareRange(base, index, -1, oldExtension, 0, -1, FALSE) == 0) { base = Unicode_Truncate(oldBase, index); // remove '.' break; } } va_end(arguments); } else { /* Always truncate the old extension if extension list is empty . */ base = Unicode_Truncate(oldBase, index); // remove '.' } if (oldBase != base) { Unicode_Free(oldBase); } } if (Unicode_IsEmpty(path)) { result = Unicode_Append(base, newExtension); } else { result = Unicode_Join(path, DIRSEPS, base, newExtension, NULL); } Unicode_Free(path); Unicode_Free(base); return result; }
void File_SplitName(ConstUnicode pathName, // IN: Unicode *volume, // OUT (OPT): Unicode *directory, // OUT (OPT): Unicode *base) // OUT (OPT): { Unicode vol; Unicode dir; Unicode bas; UnicodeIndex volEnd; UnicodeIndex length; UnicodeIndex baseBegin; WIN32_ONLY(UnicodeIndex pathLen); ASSERT(pathName); /* * Get volume. */ volEnd = 0; #if defined(_WIN32) pathLen = Unicode_LengthInCodePoints(pathName); if ((pathLen > 2) && (Unicode_StartsWith(pathName, "\\\\") || Unicode_StartsWith(pathName, "//"))) { /* UNC path */ volEnd = FileFirstSlashIndex(pathName, 2); if (volEnd == UNICODE_INDEX_NOT_FOUND) { /* we have \\foo, which is just bogus */ volEnd = 0; } else { volEnd = FileFirstSlashIndex(pathName, volEnd + 1); if (volEnd == UNICODE_INDEX_NOT_FOUND) { /* we have \\foo\bar, which is legal */ volEnd = pathLen; } } } else if ((pathLen >= 2) && (Unicode_FindSubstrInRange(pathName, 1, 1, ":", 0, 1) != UNICODE_INDEX_NOT_FOUND)) { /* drive-letter path */ volEnd = 2; } if (volEnd > 0) { vol = Unicode_Substr(pathName, 0, volEnd); } else { vol = Unicode_Duplicate(""); } #else vol = Unicode_Duplicate(""); #endif /* _WIN32 */ /* * Get base. */ baseBegin = FileLastSlashIndex(pathName, 0); baseBegin = (baseBegin == UNICODE_INDEX_NOT_FOUND) ? 0 : baseBegin + 1; if (baseBegin >= volEnd) { bas = Unicode_Substr(pathName, baseBegin, -1); } else { bas = Unicode_Duplicate(""); } /* * Get dir. */ length = baseBegin - volEnd; if (length > 0) { dir = Unicode_Substr(pathName, volEnd, length); } else { dir = Unicode_Duplicate(""); } /* * Return what needs to be returned. */ if (volume) { *volume = vol; } else { Unicode_Free(vol); } if (directory) { *directory = dir; } else { Unicode_Free(dir); } if (base) { *base = bas; } else { Unicode_Free(bas); } }
static int Scanner(ConstUnicode lockDir, // IN: int (*func)( // IN: ConstUnicode lockDir, ConstUnicode fileName, LockValues *memberValues, LockValues *myValues ), LockValues *myValues, // IN: Bool cleanUp) // IN: { int err; ActiveLock *ptr; ASSERT(lockDir); myValues->lockList = NULL; while (TRUE) { ActiveLock *prev; err = ScanDirectory(lockDir, func, myValues, cleanUp); if ((err > 0) || ((err == 0) && (myValues->lockList == NULL))) { break; } prev = NULL; ptr = myValues->lockList; /* * Some 'D' entries have persisted. Age them and remove those that * have not progressed. Remove those that have disappeared. */ while (ptr != NULL) { Bool remove; if (ptr->marked) { if (ptr->age > FILELOCK_PROGRESS_DEARTH) { Unicode temp; Unicode path; UnicodeIndex index; ASSERT(Unicode_StartsWith(ptr->dirName, "D")); Log(LGPFX" %s discarding %s data from '%s'.\n", __FUNCTION__, UTF8(ptr->dirName), UTF8(lockDir)); path = Unicode_Join(lockDir, DIRSEPS, ptr->dirName, NULL); index = Unicode_FindLast(path, "D"); ASSERT(index != UNICODE_INDEX_NOT_FOUND); temp = Unicode_Replace(path, index, 1, "M"); FileDeletionRobust(temp, FALSE); Unicode_Free(temp); temp = Unicode_Replace(path, index, 1, "E"); FileDeletionRobust(temp, FALSE); Unicode_Free(temp); FileRemoveDirectoryRobust(path); Unicode_Free(path); remove = TRUE; } else { ptr->marked = FALSE; ptr->age += FILELOCK_PROGRESS_SAMPLE; remove = FALSE; } } else { remove = TRUE; } if (remove) { if (prev == NULL) { myValues->lockList = ptr->next; } else { prev->next = ptr->next; } } prev = ptr; ptr = ptr->next; } FileSleeper(FILELOCK_PROGRESS_SAMPLE); // relax } /* Clean up anything still on the list; they are no longer important */ while (myValues->lockList != NULL) { ptr = myValues->lockList; myValues->lockList = ptr->next; Unicode_Free(ptr->dirName); free(ptr); } return err; }
static int ScanDirectory(ConstUnicode lockDir, // IN: int (*func)( // IN: ConstUnicode lockDir, ConstUnicode fileName, LockValues *memberValues, LockValues *myValues ), LockValues *myValues, // IN: Bool cleanUp) // IN: { uint32 i; int err; int numEntries; Unicode *fileList = NULL; char *myExecutionID = NULL; char *locationChecksum = NULL; ASSERT(lockDir); numEntries = FileListDirectoryRobust(lockDir, &fileList); if (numEntries == -1) { Log(LGPFX" %s: Could not read the directory '%s': %d\n", __FUNCTION__, UTF8(lockDir), Err_Errno()); return EDOM; // out of my domain } /* Pass 1: Validate entries and handle any 'D' entries */ for (i = 0, err = 0; i < numEntries; i++) { /* Remove any non-locking files */ if (!FileLockValidName(fileList[i])) { Log(LGPFX" %s discarding %s from %s'; invalid file name.\n", __FUNCTION__, UTF8(fileList[i]), UTF8(lockDir)); err = RemoveLockingFile(lockDir, fileList[i]); if (err != 0) { goto bail; } Unicode_Free(fileList[i]); fileList[i] = NULL; continue; } /* * Any lockers appear to be entering? * * This should be rather rare. If a locker dies while entering * this will cleaned-up. */ if (Unicode_StartsWith(fileList[i], "D")) { if (cleanUp) { err = ActivateLockList(fileList[i], myValues); if (err != 0) { goto bail; } } Unicode_Free(fileList[i]); fileList[i] = NULL; } } if (myValues->lockList != NULL) { goto bail; } myExecutionID = FileLockGetExecutionID(); locationChecksum = FileLockLocationChecksum(lockDir); /* Pass 2: Handle the 'M' entries */ for (i = 0, err = 0; i < numEntries; i++) { LockValues *ptr; Bool myLockFile; LockValues memberValues; char buffer[FILELOCK_DATA_SIZE]; if ((fileList[i] == NULL) || (Unicode_StartsWith(fileList[i], "E"))) { continue; } myLockFile = (Unicode_Compare(fileList[i], myValues->memberName) == 0) ? TRUE : FALSE; if (myLockFile) { /* It's me! No need to read or validate anything. */ ptr = myValues; } else { /* It's not me! Attempt to extract the member values. */ err = FileLockMemberValues(lockDir, fileList[i], buffer, FILELOCK_DATA_SIZE, &memberValues); if (err != 0) { if (err == ENOENT) { err = 0; /* Not there anymore; locker unlocked or timed out */ continue; } break; } /* Remove any stale locking files */ if (FileLockMachineIDMatch(myValues->machineID, memberValues.machineID)) { char *dispose = NULL; if (FileLockValidOwner(memberValues.executionID, memberValues.payload)) { /* If it's mine it better still be where I put it! */ if ((strcmp(myExecutionID, memberValues.executionID) == 0) && ((memberValues.locationChecksum != NULL) && (strcmp(memberValues.locationChecksum, locationChecksum) != 0))) { dispose = "lock file has been moved."; } } else { dispose = "invalid executionID."; } if (dispose) { Log(LGPFX" %s discarding %s from %s': %s\n", __FUNCTION__, UTF8(fileList[i]), UTF8(lockDir), dispose); Unicode_Free(memberValues.memberName); err = RemoveLockingFile(lockDir, fileList[i]); if (err != 0) { break; } continue; } } ptr = &memberValues; } /* Locking file looks good; see what happens */ err = (*func)(lockDir, fileList[i], ptr, myValues); if (ptr == &memberValues) { Unicode_Free(memberValues.memberName); } if (err != 0) { break; } } bail: for (i = 0; i < numEntries; i++) { Unicode_Free(fileList[i]); } free(fileList); free(locationChecksum); free(myExecutionID); return err; }