Unicode Unicode_ReplaceRange(ConstUnicode destination, // IN UnicodeIndex destinationStart, // IN UnicodeIndex destinationLength, // IN ConstUnicode source, // IN UnicodeIndex sourceStart, // IN UnicodeIndex sourceLength) // IN { UnicodeIndex destNumCodeUnits; UnicodeIndex resultLength; char *result; UnicodePinIndices(destination, &destinationStart, &destinationLength); UnicodePinIndices(source, &sourceStart, &sourceLength); destNumCodeUnits = Unicode_LengthInCodeUnits(destination); resultLength = destNumCodeUnits - destinationLength + sourceLength; result = Util_SafeMalloc(resultLength + 1); // Start with the destination bytes before the substring to be replaced. memcpy(result, destination, destinationStart); // Insert the substring of source in place of the destination substring. memcpy(result + destinationStart, (const char *)source + sourceStart, sourceLength); // Append the remaining bytes of destination after the replaced substring. memcpy(result + destinationStart + sourceLength, (const char *)destination + destinationStart + destinationLength, destNumCodeUnits - destinationStart - destinationLength); result[resultLength] = '\0'; return (Unicode)result; }
void * FileLockIntrinsic(ConstUnicode pathName, // IN: Bool exclusivity, // IN: uint32 msecMaxWaitTime, // IN: const char *payload, // IN: int *err) // OUT: { FILELOCK_FILE_HANDLE handle; LockValues myValues; Unicode lockDir = NULL; Unicode entryFilePath = NULL; Unicode memberFilePath = NULL; Unicode entryDirectory = NULL; ASSERT(pathName); ASSERT(err); /* Construct the locking directory path */ lockDir = Unicode_Append(pathName, FILELOCK_SUFFIX); /* establish our values */ myValues.machineID = (char *) FileLockGetMachineID(); // don't free this! myValues.executionID = FileLockGetExecutionID(); // free this! myValues.payload = (char *) payload; myValues.lockType = exclusivity ? LOCK_EXCLUSIVE : LOCK_SHARED; myValues.lamportNumber = 0; myValues.locationChecksum = FileLockLocationChecksum(lockDir); // free this! myValues.waitTime = 0; myValues.msecMaxWaitTime = msecMaxWaitTime; myValues.memberName = NULL; LOG(1, ("Requesting %s lock on %s (%s, %s, %u).\n", myValues.lockType, UTF8(pathName), myValues.machineID, myValues.executionID, myValues.msecMaxWaitTime)); /* * Attempt to create the locking and entry directories; obtain the * entry and member path names. */ *err = CreateEntryDirectory(myValues.machineID, myValues.executionID, lockDir, &entryDirectory, &entryFilePath, &memberFilePath, &myValues.memberName); switch (*err) { case 0: break; case EROFS: /* FALL THROUGH */ case EACCES: if (!exclusivity) { /* * Lock is for read/shared access however the lock directory could * not be created. Grant an implicit read lock whenever possible. * The address of a private variable will be used for the lock token. */ Warning(LGPFX" %s implicit %s lock succeeded on '%s'.\n", __FUNCTION__, LOCK_SHARED, UTF8(pathName)); *err = 0; memberFilePath = &implicitReadToken; } /* FALL THROUGH */ default: goto bail; } ASSERT(Unicode_LengthInCodeUnits(memberFilePath) - Unicode_LengthInCodeUnits(pathName) <= FILELOCK_OVERHEAD); /* Attempt to create the entry file */ *err = FileLockOpenFile(entryFilePath, O_CREAT | O_WRONLY, &handle); if (*err != 0) { /* clean up */ FileRemoveDirectoryRobust(entryDirectory); FileRemoveDirectoryRobust(lockDir); goto bail; } /* what is max(Number[1]... Number[all lockers])? */ *err = Scanner(lockDir, NumberScan, &myValues, FALSE); if (*err != 0) { /* clean up */ FileLockCloseFile(handle); FileDeletionRobust(entryFilePath, FALSE); FileRemoveDirectoryRobust(entryDirectory); FileRemoveDirectoryRobust(lockDir); goto bail; } /* Number[i] = 1 + max([Number[1]... Number[all lockers]) */ myValues.lamportNumber++; /* Attempt to create the member file */ *err = CreateMemberFile(handle, &myValues, entryFilePath, memberFilePath); /* Remove entry directory; it has done its job */ FileRemoveDirectoryRobust(entryDirectory); if (*err != 0) { /* clean up */ FileDeletionRobust(entryFilePath, FALSE); FileDeletionRobust(memberFilePath, FALSE); FileRemoveDirectoryRobust(lockDir); goto bail; } /* Attempt to acquire the lock */ *err = Scanner(lockDir, WaitForPossession, &myValues, TRUE); switch (*err) { case 0: break; case EAGAIN: /* clean up */ FileDeletionRobust(memberFilePath, FALSE); FileRemoveDirectoryRobust(lockDir); /* FALL THROUGH */ default: break; } bail: Unicode_Free(lockDir); Unicode_Free(entryDirectory); Unicode_Free(entryFilePath); Unicode_Free(myValues.memberName); free(myValues.locationChecksum); free(myValues.executionID); if (*err != 0) { Unicode_Free(memberFilePath); memberFilePath = NULL; if (*err == EAGAIN) { *err = 0; // lock not acquired } } return (void *) memberFilePath; }