static char * ExtractArgStringFromAddressSpaceFile(FileIODescriptor asFd, //IN uintptr_t offset) //IN { int readSize = 32; char *buf; FileIOResult res; buf = Util_SafeMalloc(readSize * sizeof *buf); while (1) { res = FileIO_Pread(&asFd, buf, readSize, offset); if (res != FILEIO_SUCCESS) { goto fail; } if (Str_Strlen(buf, readSize) == readSize) { readSize *= 2; free(buf); if (readSize > NCARGS) { return NULL; } buf = Util_SafeMalloc(readSize * sizeof *buf); } else { break; } } return buf; fail: free(buf); return NULL; }
size_t DnD_TransportBufGetPacket(DnDTransportBuffer *buf, // IN/OUT DnDTransportPacketHeader **packet) // OUT { size_t payloadSize; ASSERT(buf); if (buf->totalSize < buf->offset) { return 0; } if ((buf->totalSize - buf->offset) > DND_MAX_TRANSPORT_PACKET_PAYLOAD_SIZE) { payloadSize = DND_MAX_TRANSPORT_PACKET_PAYLOAD_SIZE; } else { payloadSize = buf->totalSize - buf->offset; } *packet = Util_SafeMalloc(payloadSize + DND_TRANSPORT_PACKET_HEADER_SIZE); (*packet)->type = DND_TRANSPORT_PACKET_TYPE_PAYLOAD; (*packet)->seqNum = buf->seqNum; (*packet)->totalSize = buf->totalSize; (*packet)->payloadSize = payloadSize; (*packet)->offset = buf->offset; memcpy((*packet)->payload, buf->buffer + buf->offset, payloadSize); buf->offset += payloadSize; /* This time is used for timeout purpose. */ buf->lastUpdateTime = Hostinfo_SystemTimerUS(); return payloadSize + DND_TRANSPORT_PACKET_HEADER_SIZE; }
size_t DnD_TransportMsgToPacket(uint8 *msg, // IN size_t msgSize, // IN uint32 seqNum, // IN DnDTransportPacketHeader **packet) // OUT { size_t packetSize; ASSERT(msgSize > 0 && msgSize <= DND_MAX_TRANSPORT_PACKET_PAYLOAD_SIZE); ASSERT(msg); ASSERT(packet); if (msgSize <=0 || msgSize > DND_MAX_TRANSPORT_PACKET_PAYLOAD_SIZE || !msg || !packet) { return 0; } packetSize = msgSize + DND_TRANSPORT_PACKET_HEADER_SIZE; *packet = Util_SafeMalloc(packetSize); (*packet)->type = DND_TRANSPORT_PACKET_TYPE_SINGLE; (*packet)->seqNum = seqNum; (*packet)->totalSize = msgSize; (*packet)->payloadSize = msgSize; (*packet)->offset = 0; memcpy((*packet)->payload, msg, msgSize); return packetSize; }
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; }
Unicode * Unicode_AllocList(char **srcList, // IN: list of strings ssize_t length, // IN: list StringEncoding encoding) // IN: { Unicode *dstList = NULL; ssize_t i; ASSERT(srcList != NULL); encoding = Unicode_ResolveEncoding(encoding); if (length < 0) { length = 0; while (srcList[length] != NULL) { length++; } /* Include the sentinel element. */ length++; } dstList = Util_SafeMalloc(length * sizeof *dstList); for (i = 0; i < length; i++) { dstList[i] = Unicode_Alloc(srcList[i], encoding); } return dstList; }
char * Unicode_ToTitle(const char *str, // IN const char *locale) // IN { UCaseMap *caseMap; UErrorCode status = U_ZERO_ERROR; char *utf8Dest; const char *utf8Src = (const char *)str; int32_t utf8SrcLen = strlen(utf8Src); int32_t destCapacity = utf8SrcLen + 1; int32_t destLen; char *result = NULL; // Most title-case operations don't change the length of the string. utf8Dest = (char *)Util_SafeMalloc(destCapacity); caseMap = ucasemap_open(locale, 0, &status); if (U_FAILURE(status)) { goto out; } destLen = ucasemap_utf8ToTitle(caseMap, utf8Dest, destCapacity, utf8Src, utf8SrcLen, &status); if (status != U_BUFFER_OVERFLOW_ERROR) { goto out; } // If we need a bigger buffer, then reallocate and retry. destCapacity = destLen + 1; utf8Dest = (char *)Util_SafeRealloc(utf8Dest, destCapacity); status = U_ZERO_ERROR; destLen = ucasemap_utf8ToTitle(caseMap, utf8Dest, destCapacity, utf8Src, utf8SrcLen, &status); out: ucasemap_close(caseMap); if (U_SUCCESS(status) && status != U_STRING_NOT_TERMINATED_WARNING) { result = utf8Dest; } else { ASSERT(U_SUCCESS(status)); ASSERT(status != U_STRING_NOT_TERMINATED_WARNING); } return result; }
VixError VixToolsNewEnvIterator(void *userToken, // IN #ifdef __FreeBSD__ char **envp, // IN #endif VixToolsEnvIterator **envItr) // OUT { VixError err = VIX_OK; VixToolsEnvIterator *it = Util_SafeMalloc(sizeof *it); if (NULL == envItr) { err = VIX_E_FAIL; goto abort; } *envItr = NULL; #ifdef _WIN32 if (PROCESS_CREATOR_USER_TOKEN != userToken) { /* * The process is impersonating a user, so retrieve the user's * environment block instead of using the process's environment. */ it->envType = VIX_TOOLS_ENV_TYPE_ENV_BLOCK; err = VixToolsGetEnvBlock(userToken, &it->data.eb.envBlock); if (VIX_FAILED(err)) { goto abort; } it->data.eb.currEnvVar = it->data.eb.envBlock; } else { /* * The action is being performed as the user running the process * so the process's environment is fine. * TODO: Is this totally equivilent to the behavior when impersonated? * Would fetching the environment block include changes to the user's * or system's environment made after the process is running? */ it->envType = VIX_TOOLS_ENV_TYPE_ENVIRON; it->data.environ = _wenviron; } #elif defined(__APPLE__) it->environ = *_NSGetEnviron(); #elif defined(__FreeBSD__) it->environ = envp; #else it->environ = environ; #endif *envItr = it; abort: if (VIX_FAILED(err)) { free(it); } return err; }
VMIOVec* IOV_Allocate(int numEntries) // IN { struct VMIOVecAndEntries *iov; iov = Util_SafeMalloc(sizeof *iov + numEntries * sizeof(struct iovec)); iov->iov.entries = iov->e; iov->iov.allocEntries = NULL; iov->iov.numEntries = numEntries; return &iov->iov; }
LONG Win32U_RegEnumValue(HKEY keyName, // IN DWORD index, // IN LPSTR valueName, // OUT: buffer LPDWORD valueNameSize, // IN/OUT: LPDWORD reserved, // IN: reserved LPDWORD type, // OUT: can be NULL LPBYTE data, // OUT: can be NULL LPDWORD dataSize) // OUT: can be NULL { LONG ret; utf16_t *valueNameW; DWORD valueNameSizeW = REG_MAX_VALUE_NAME_LEN+1; char *dataTemp = NULL; DWORD dataSizeTemp = 0; DWORD valueType; valueNameW = Util_SafeCalloc(valueNameSizeW, sizeof *valueNameW); if (data) { ASSERT(dataSize != NULL); dataSizeTemp = *dataSize * 2; dataTemp = Util_SafeMalloc(dataSizeTemp); } ret = RegEnumValueW(keyName, index, valueNameW, &valueNameSizeW /* # of characters */, reserved, &valueType, dataTemp, &dataSizeTemp /* # of bytes */); if (ret != ERROR_NO_MORE_ITEMS) { /* valueName is valid */ /* Attempt to convert value name back to UTF-8 */ if (!Win32UCodeSetUtf16leToUtf8(valueNameW, valueNameSizeW * 2, valueName, valueNameSize)) { ret = ERROR_MORE_DATA; } } ret = Win32UWriteBackRegData(dataTemp, dataSizeTemp, data, dataSize, valueType, ret); /* Write back the type information if asked for */ if (type) { *type = valueType; } free(valueNameW); free(dataTemp); return ret; }
size_t DnD_TransportReqPacket(DnDTransportBuffer *buf, // IN DnDTransportPacketHeader **packet) // OUT { *packet = Util_SafeMalloc(DND_TRANSPORT_PACKET_HEADER_SIZE); (*packet)->type = DND_TRANSPORT_PACKET_TYPE_REQUEST; (*packet)->seqNum = buf->seqNum; (*packet)->totalSize = buf->totalSize; (*packet)->payloadSize = 0; (*packet)->offset = buf->offset; return DND_TRANSPORT_PACKET_HEADER_SIZE; }
Bool DnD_TransportBufAppendPacket(DnDTransportBuffer *buf, // IN/OUT DnDTransportPacketHeader *packet, // IN size_t packetSize) // IN { ASSERT(buf); ASSERT(packetSize == (packet->payloadSize + DND_TRANSPORT_PACKET_HEADER_SIZE) && packetSize <= DND_MAX_TRANSPORT_PACKET_SIZE && (packet->payloadSize + packet->offset) <= packet->totalSize && packet->totalSize <= DNDMSG_MAX_ARGSZ); if (packetSize != (packet->payloadSize + DND_TRANSPORT_PACKET_HEADER_SIZE) || packetSize > DND_MAX_TRANSPORT_PACKET_SIZE || (packet->payloadSize + packet->offset) > packet->totalSize || packet->totalSize > DNDMSG_MAX_ARGSZ) { goto error; } /* * If seqNum does not match, it means either this is the first packet, or there * is a timeout in another side. Reset the buffer in all cases. */ if (buf->seqNum != packet->seqNum) { DnD_TransportBufReset(buf); } if (!buf->buffer) { ASSERT(!packet->offset); if (packet->offset) { goto error; } buf->buffer = Util_SafeMalloc(packet->totalSize); buf->totalSize = packet->totalSize; buf->seqNum = packet->seqNum; buf->offset = 0; } if (buf->offset != packet->offset) { goto error; } memcpy(buf->buffer + buf->offset, packet->payload, packet->payloadSize); buf->offset += packet->payloadSize; return TRUE; error: DnD_TransportBufReset(buf); return FALSE; }
/* Duplicate a buffer --hpreg. The result is NUL-terminated */ static void * BufDup(void const * const bufIn, // IN: buffer to duplicate unsigned int const sizeIn) // IN: buffer size in bytes { char *bufOut; ASSERT(bufIn); bufOut = Util_SafeMalloc(sizeIn + 1); memcpy(bufOut, bufIn, sizeIn); bufOut[sizeIn] = '\0'; return bufOut; }
VMIOVec* IOV_Duplicate(VMIOVec* iovIn) // IN { struct VMIOVecAndEntries* v; v = Util_SafeMalloc(sizeof *v + iovIn->numEntries * sizeof(struct iovec)); Util_Memcpy(&v->iov, iovIn, sizeof *iovIn); v->iov.allocEntries = NULL; v->iov.entries = v->e; Util_Memcpy(v->iov.entries, iovIn->entries, iovIn->numEntries * sizeof(struct iovec)); return &v->iov; }
void * UnicodeGetAllocBytesInternal(ConstUnicode ustr, // IN StringEncoding encoding, // IN ssize_t lengthInBytes, // IN size_t *retLength) // OUT: optional { const char *utf8Str = ustr; char *result = NULL; ASSERT(ustr != NULL); encoding = Unicode_ResolveEncoding(encoding); if (lengthInBytes == -1) { lengthInBytes = Unicode_LengthInBytes(ustr, STRING_ENCODING_UTF8); } switch (encoding) { case STRING_ENCODING_US_ASCII: if (!UnicodeSanityCheck(utf8Str, lengthInBytes, encoding)) { break; } // fall through case STRING_ENCODING_UTF8: result = Util_SafeMalloc(lengthInBytes + 1); memcpy(result, utf8Str, lengthInBytes + 1); if (retLength != NULL) { *retLength = lengthInBytes; } break; case STRING_ENCODING_UTF16_LE: if (!CodeSet_Utf8ToUtf16le(utf8Str, lengthInBytes, &result, retLength)) { // input should be valid UTF-8, no conversion error possible ASSERT_MEM_ALLOC(FALSE); } break; default: if (!CodeSet_GenericToGeneric("UTF-8", utf8Str, lengthInBytes, Unicode_EncodingEnumToName(encoding), CSGTG_NORMAL, &result, retLength)) { // XXX can't distinguish error cause ASSERT(result == NULL); } } return result; }
static MsgList * MsgId2MsgList(const char *idFmt) // IN message ID and English message { MsgList *m; const char *idp, *strp; /* All message strings must be prefixed by the message ID. */ ASSERT(Msg_HasMsgID(idFmt)); /* * Find the beginning of the ID (idp) and the string (strp). * The string should have the correct MSG_MAGIC(...)... form. */ idp = idFmt + MSG_MAGIC_LEN + 1; strp = strchr(idp, ')') + 1; m = Util_SafeMalloc(sizeof *m); m->format = Util_SafeStrdup(strp); m->next = NULL; m->args = NULL; m->numArgs = 0; if (vmx86_debug) { uint32 i; static const char *prfx[] = { "msg.", // bora/lib, VMX, ... "vob.", // Vmkernel OBservation "vpxa.", // VirtualCenter host agent "vpxd.", // VirtualCenter server "hostd.", // Host agent // Additional prefixes go here, but do not add "button." }; for (i = 0; i < ARRAYSIZE(prfx); i++) { if (!Str_Strncasecmp(idp, prfx[i], strlen(prfx[i]))) { break; } } if (i >= ARRAYSIZE(prfx)) { Panic("%s error: Invalid msg prefix in <%s>\n", __FUNCTION__, idp); } } m->id = Util_SafeStrndup(idp, strp - idp - 1 /* ')' character */); return m; }
void DnD_TransportBufInit(DnDTransportBuffer *buf, // OUT uint8 *msg, // IN size_t msgSize, // IN uint32 seqNum) // IN { ASSERT(buf); ASSERT(msgSize <= DNDMSG_MAX_ARGSZ); free(buf->buffer); buf->buffer = Util_SafeMalloc(msgSize); memcpy(buf->buffer, msg, msgSize); buf->seqNum = seqNum; buf->totalSize = msgSize; buf->offset = 0; }
/** * * Panic * * Used by VMware libraries pass PANIC signals to the parent application. * * @param fmstr [in] Format to print the arguments in. * @param args [in] Argument list. * **/ NORETURN void Panic(const char *fmtstr, ...) { va_list args; char *tmp = Util_SafeMalloc(MAXSTRING); va_start(args, fmtstr); vsprintf(tmp, fmtstr, args); va_end(args); sLog(log_error, "Panic callback invoked: %s\n", tmp); free(tmp); exit(1); }
/** * * Debug * * Mechanism used by VMware libraries to pass debug messages to the parent. * * @param fmstr [in] Format to print the arguments in. * @param args [in] Argument list. * **/ void Debug(const char *fmtstr, ...) { #ifdef VMX86_DEBUG va_list args; char *tmp = Util_SafeMalloc(MAXSTRING); va_start(args, fmtstr); vsprintf(tmp, fmtstr, args); va_end(args); sLog(log_debug, "Debug callback invoked: %s\n", tmp); free(tmp); #endif }
utf16_t * Unicode_UTF16Strdup(const utf16_t *utf16) // IN: May be NULL. { utf16_t *copy; ssize_t numBytes; // Follow Util_SafeStrdup semantics. if (utf16 == NULL) { return NULL; } numBytes = (Unicode_UTF16Strlen(utf16) + 1 /* NUL */) * sizeof *copy; copy = Util_SafeMalloc(numBytes); memcpy(copy, utf16, numBytes); return copy; }
char * StrUtil_ReplaceAll(const char *orig, // IN const char *what, // IN const char *with) // IN { char *result; const char *current; char *tmp; size_t lenWhat; size_t lenWith; size_t lenBefore; size_t occurrences = 0; size_t lenNew; ASSERT(orig != NULL); ASSERT(!StrUtil_IsEmpty(what)); ASSERT(with != NULL); lenWhat = strlen(what); lenWith = strlen(with); current = orig; while ((tmp = strstr(current, what)) != NULL) { current = tmp + lenWhat; ++occurrences; } lenNew = strlen(orig) + (lenWith - lenWhat) * occurrences; tmp = Util_SafeMalloc(lenNew + 1); result = tmp; while (occurrences--) { current = strstr(orig, what); lenBefore = current - orig; tmp = memcpy(tmp, orig, lenBefore); tmp += lenBefore; tmp = memcpy(tmp, with, lenWith); tmp += lenWith; orig += lenBefore + lenWhat; } memcpy(tmp, orig, strlen(orig)); result[lenNew] = '\0'; return result; }
char * StrUtil_GetNextToken(unsigned int *index, // IN/OUT: Index to start at const char *str, // IN : String to parse const char *delimiters) // IN : Chars separating tokens { unsigned int startIndex; unsigned int length; char *token; ASSERT(index); ASSERT(str); ASSERT(delimiters); ASSERT(*index <= strlen(str)); #define NOT_DELIMITER (Str_Strchr(delimiters, str[*index]) == NULL) /* Skip leading delimiters. */ for (; ; (*index)++) { if (str[*index] == '\0') { return NULL; } if (NOT_DELIMITER) { break; } } startIndex = *index; /* * Walk the string until we reach the end of it, or we find a * delimiter. */ for ((*index)++; str[*index] != '\0' && NOT_DELIMITER; (*index)++) { } #undef NOT_DELIMITER length = *index - startIndex; ASSERT(length); token = Util_SafeMalloc(length + 1 /* NUL */); memcpy(token, str + startIndex, length); token[length] = '\0'; return token; }
void MXUser_SetStatsFunc(void *context, // IN: uint32 maxLineLength, // IN: Bool trackHeldTimes, // IN: void (*statsFunc)(void *context, // IN: const char *fmt, va_list ap)) { ASSERT(maxLineLength >= 1024); // assert a rational minimum free(mxUserHistoLine); mxUserHistoLine = Util_SafeMalloc(maxLineLength); mxUserStatsContext = context; mxUserMaxLineLength = maxLineLength; mxUserStatsFunc = statsFunc; mxUserTrackHeldTimes = trackHeldTimes; }
MsgList * MsgList_Copy(const MsgList *src) // IN: { MsgList *result = NULL; MsgList **pdst = &result; while (src != NULL) { MsgList *dst = Util_SafeMalloc(sizeof *dst); dst->id = Util_SafeStrdup(src->id); dst->format = Util_SafeStrdup(src->format); dst->args = MsgFmt_CopyArgs(src->args, src->numArgs); dst->numArgs = src->numArgs; dst->next = NULL; src = src->next; *pdst = dst; pdst = &dst->next; } return result; }
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 IOV_DuplicateStatic(VMIOVec *iovIn, // IN int numStaticEntries, // IN struct iovec *staticEntries, // IN VMIOVec *iovOut) // OUT { ASSERT(staticEntries); ASSERT(iovIn); ASSERT(iovOut); Util_Memcpy(iovOut, iovIn, sizeof *iovOut); if (iovIn->numEntries <= numStaticEntries) { iovOut->allocEntries = NULL; iovOut->entries = staticEntries; } else { iovOut->allocEntries = Util_SafeMalloc(iovIn->numEntries * sizeof(struct iovec)); iovOut->entries = iovOut->allocEntries; } Util_Memcpy(iovOut->entries, iovIn->entries, iovIn->numEntries * sizeof(struct iovec)); }
static int SNEForEachCallback(const char *key, // IN: environment variable void *value, // IN: environment value void *clientData) // IN/OUT: DynBuf container (SNEBufs) { DynBuf *nativeEnvironStrings = ((SNEBufs *)clientData)->nativeEnvironStrings; DynBuf *nativeEnvironOffsets = ((SNEBufs *)clientData)->nativeEnvironOffsets; size_t itemSize; char *itemBuf; off_t itemOffset; /* * A NULL value indicates that this variable is not to be set. */ if (value == NULL) { return 0; } /* Determine the length of the new string inc. '=' delimiter and NUL. */ itemSize = strlen(key) + strlen(value) + sizeof "="; itemBuf = Util_SafeMalloc(itemSize); /* Create new "key=value" string. */ snprintf(itemBuf, itemSize, "%s=%s", key, (char *)value); ASSERT_MEM_ALLOC(DynBuf_AppendString(nativeEnvironStrings, itemBuf)); /* * Get the relative offset of our newly added string (relative to the DynBuf's base * address), and then append that to nativeEnvironOffsets. */ itemOffset = DynBuf_GetSize(nativeEnvironStrings) - itemSize; ASSERT_MEM_ALLOC(DynBuf_Append(nativeEnvironOffsets, &itemOffset, sizeof itemOffset)); free(itemBuf); return 0; }
Bool CodeSet_UTF8ToUTF32(const char *utf8, // IN: char **utf32) // OUT: { char *p; char *end; uint32 *ptr; int codePoints; ASSERT(utf32); if (utf8 == NULL) { // NULL is not an error *utf32 = NULL; return TRUE; } codePoints = CodeSet_LengthInCodePoints(utf8); if (codePoints == -1) { *utf32 = NULL; return FALSE; } p = (char *) utf8; end = p + strlen(utf8); ptr = Util_SafeMalloc(sizeof *ptr * (codePoints + 1)); *utf32 = (char *) ptr; while (p < end) { p += CodeSet_GetUtf8(p, end, ptr++); } *ptr = 0; return TRUE; }
VixError VixToolsNewUserEnvironment(void *userToken, // IN VixToolsUserEnvironment **env) // OUT { VixError err = VIX_OK; VixToolsUserEnvironment *myEnv = Util_SafeMalloc(sizeof *myEnv); if (NULL == env) { err = VIX_E_FAIL; goto abort; } *env = NULL; #ifdef _WIN32 if (PROCESS_CREATOR_USER_TOKEN != userToken) { myEnv->impersonated = TRUE; err = VixToolsGetEnvBlock(userToken, &myEnv->envBlock); if (VIX_FAILED(err)) { goto abort; } } else { myEnv->impersonated = FALSE; /* We will just read from the process's environment. */ } #endif *env = myEnv; abort: if (VIX_FAILED(err)) { free(myEnv); } return err; }
static HolderContext * MXUserGetHolderContext(MXUserRWLock *lock) // IN: { HolderContext *result; void *threadID = MXUserCastedThreadID(); ASSERT(lock->holderTable); if (!HashTable_Lookup(lock->holderTable, threadID, (void **) &result)) { HolderContext *newContext = Util_SafeMalloc(sizeof(HolderContext)); newContext->holdStart = 0; newContext->state = RW_UNLOCKED; result = HashTable_LookupOrInsert(lock->holderTable, threadID, (void *) newContext); if (result != newContext) { free(newContext); } } return result; }
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; }