static void testCopyEx1(RTTEST hTest) { RTTestISub("RTStrCopyEx"); char *pszBuf4H = (char *)RTTestGuardedAllocHead(hTest, 4); char *pszBuf4T = (char *)RTTestGuardedAllocTail(hTest, 4); RTTESTI_CHECK_RC(RTStrCopyEx(pszBuf4H, 4, "abc", RTSTR_MAX), VINF_SUCCESS); RTTESTI_CHECK(strcmp(pszBuf4H, "abc") == 0); RTTESTI_CHECK_RC(RTStrCopyEx(pszBuf4T, 4, "abc", RTSTR_MAX), VINF_SUCCESS); RTTESTI_CHECK(strcmp(pszBuf4T, "abc") == 0); RT_BZERO(pszBuf4H, 4); RT_BZERO(pszBuf4T, 4); RTTESTI_CHECK_RC(RTStrCopyEx(pszBuf4H, 4, "abcd", RTSTR_MAX), VERR_BUFFER_OVERFLOW); RTTESTI_CHECK(strcmp(pszBuf4H, "abc") == 0); RTTESTI_CHECK_RC(RTStrCopyEx(pszBuf4T, 4, "abcd", RTSTR_MAX), VERR_BUFFER_OVERFLOW); RTTESTI_CHECK(strcmp(pszBuf4T, "abc") == 0); RT_BZERO(pszBuf4H, 4); RT_BZERO(pszBuf4T, 4); RTTESTI_CHECK_RC(RTStrCopyEx(pszBuf4H, 4, "abcd", 3), VINF_SUCCESS); RTTESTI_CHECK(strcmp(pszBuf4H, "abc") == 0); RTTESTI_CHECK_RC(RTStrCopyEx(pszBuf4T, 4, "abcd", 3), VINF_SUCCESS); RTTESTI_CHECK(strcmp(pszBuf4T, "abc") == 0); RT_BZERO(pszBuf4H, 4); RT_BZERO(pszBuf4T, 4); RTTESTI_CHECK_RC(RTStrCopyEx(pszBuf4H, 4, "abcd", 2), VINF_SUCCESS); RTTESTI_CHECK(strcmp(pszBuf4H, "ab") == 0); RTTESTI_CHECK_RC(RTStrCopyEx(pszBuf4T, 4, "abcd", 2), VINF_SUCCESS); RTTESTI_CHECK(strcmp(pszBuf4T, "ab") == 0); }
int rtPathFromNativeCopy(char *pszPath, size_t cbPath, const char *pszNativePath, const char *pszBasePath) { /** @todo We must compose the codepoints in the string here. We get file names * in normalization form D so we'll end up with normalization form C * whatever approach we take. */ int rc = RTStrValidateEncodingEx(pszNativePath, RTSTR_MAX, 0 /*fFlags*/); if (RT_SUCCESS(rc)) rc = RTStrCopyEx(pszPath, cbPath, pszNativePath, RTSTR_MAX); NOREF(pszBasePath); /* We don't query the FS for codeset preferences. */ return rc; }
/* * Converts clipboard data from CF_HTML format to mimie clipboard format * Returns allocated buffer that contains html converted to text/html mime type * return result code * parameters - output buffer and size of output buffer * It allocates the buffer needed for storing converted fragment * Allocated buffer should be destroyed by RTMemFree after usage */ int ConvertCFHtmlToMime(const char *pcszSource, const uint32_t cch, char **ppszOutput, size_t *pcCh) { char* result = NULL; Assert(pcszSource); Assert(cch); Assert(ppszOutput); Assert(pcCh); size_t cStartOffset, cEndOffset; int rc = GetHeaderValue(pcszSource, "StartFragment:", &cStartOffset); if (!RT_SUCCESS(rc)) { LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected StartFragment. rc = %Rrc.\n", rc)); return VERR_INVALID_PARAMETER; } rc = GetHeaderValue(pcszSource, "EndFragment:", &cEndOffset); if (!RT_SUCCESS(rc)) { LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected EndFragment. rc = %Rrc.\n", rc)); return VERR_INVALID_PARAMETER; } if (cStartOffset > 0 && cEndOffset > 0 && cEndOffset > cStartOffset) { size_t cSubstrlen = cEndOffset - cStartOffset; result = (char*)RTMemAlloc(cSubstrlen + 1); if (result) { RT_BZERO(result, cSubstrlen + 1); rc = RTStrCopyEx(result, cSubstrlen + 1, pcszSource + cStartOffset, cSubstrlen); if (RT_SUCCESS(rc)) { *ppszOutput = result; *pcCh = cSubstrlen + 1; } else { LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected EndFragment. rc = %Rrc\n", rc)); return rc; } } else { LogRelFlowFunc(("Error: Unknown CF_HTML format. Expected EndFragment.\n")); return VERR_NO_MEMORY; } } return VINF_SUCCESS; }
RTDECL(int) RTEnvGetByIndexEx(RTENV hEnv, uint32_t iVar, char *pszVar, size_t cbVar, char *pszValue, size_t cbValue) { PRTENVINTERNAL pIntEnv = hEnv; AssertPtrReturn(pIntEnv, UINT32_MAX); AssertReturn(pIntEnv->u32Magic == RTENV_MAGIC, UINT32_MAX); if (cbVar) AssertPtrReturn(pszVar, VERR_INVALID_POINTER); if (cbValue) AssertPtrReturn(pszValue, VERR_INVALID_POINTER); RTENV_LOCK(pIntEnv); int rc; if (iVar < pIntEnv->cVars) { const char *pszSrcVar = pIntEnv->papszEnv[iVar]; const char *pszSrcValue = strchr(pszSrcVar, '='); bool fHasEqual = pszSrcValue != NULL; if (pszSrcValue) { pszSrcValue++; rc = VINF_SUCCESS; } else { pszSrcValue = strchr(pszSrcVar, '\0'); rc = VINF_ENV_VAR_UNSET; } if (cbVar) { int rc2 = RTStrCopyEx(pszVar, cbVar, pszSrcVar, pszSrcValue - pszSrcVar - fHasEqual); if (RT_FAILURE(rc2)) rc = rc2; } if (cbValue) { int rc2 = RTStrCopy(pszValue, cbValue, pszSrcValue); if (RT_FAILURE(rc2) && RT_SUCCESS(rc)) rc = rc2; } } else rc = VERR_ENV_VAR_NOT_FOUND; RTENV_UNLOCK(pIntEnv); return rc; }
RTDECL(int) RTSystemQueryDmiString(RTSYSDMISTR enmString, char *pszBuf, size_t cbBuf) { AssertPtrReturn(pszBuf, VERR_INVALID_POINTER); AssertReturn(cbBuf > 0, VERR_INVALID_PARAMETER); *pszBuf = '\0'; AssertReturn(enmString > RTSYSDMISTR_INVALID && enmString < RTSYSDMISTR_END, VERR_INVALID_PARAMETER); CFStringRef PropStringRef = NULL; switch (enmString) { case RTSYSDMISTR_PRODUCT_NAME: PropStringRef = CFSTR(PROP_PRODUCT_NAME); break; case RTSYSDMISTR_PRODUCT_VERSION: PropStringRef = CFSTR(PROP_PRODUCT_VERSION); break; case RTSYSDMISTR_PRODUCT_SERIAL: PropStringRef = CFSTR(PROP_PRODUCT_SERIAL); break; case RTSYSDMISTR_PRODUCT_UUID: PropStringRef = CFSTR(PROP_PRODUCT_UUID); break; case RTSYSDMISTR_MANUFACTURER: PropStringRef = CFSTR(PROP_MANUFACTURER); break; default: return VERR_NOT_SUPPORTED; } mach_port_t MasterPort; kern_return_t kr = IOMasterPort(MACH_PORT_NULL, &MasterPort); if (kr != kIOReturnSuccess) { if (kr == KERN_NO_ACCESS) return VERR_ACCESS_DENIED; return RTErrConvertFromDarwinIO(kr); } CFDictionaryRef ClassToMatch = IOServiceMatching(IOCLASS_PLATFORMEXPERTDEVICE); if (!ClassToMatch) return VERR_NOT_SUPPORTED; /* IOServiceGetMatchingServices will always consume ClassToMatch. */ io_iterator_t Iterator; kr = IOServiceGetMatchingServices(MasterPort, ClassToMatch, &Iterator); if (kr != kIOReturnSuccess) return RTErrConvertFromDarwinIO(kr); int rc = VERR_NOT_SUPPORTED; io_service_t ServiceObject; while ((ServiceObject = IOIteratorNext(Iterator))) { if ( enmString == RTSYSDMISTR_PRODUCT_NAME || enmString == RTSYSDMISTR_PRODUCT_VERSION || enmString == RTSYSDMISTR_MANUFACTURER ) { CFDataRef DataRef = (CFDataRef)IORegistryEntryCreateCFProperty(ServiceObject, PropStringRef, kCFAllocatorDefault, kNilOptions); if (DataRef) { size_t cbData = CFDataGetLength(DataRef); const char *pchData = (const char *)CFDataGetBytePtr(DataRef); rc = RTStrCopyEx(pszBuf, cbBuf, pchData, cbData); CFRelease(DataRef); break; } } else { CFStringRef StringRef = (CFStringRef)IORegistryEntryCreateCFProperty(ServiceObject, PropStringRef, kCFAllocatorDefault, kNilOptions); if (StringRef) { Boolean fRc = CFStringGetCString(StringRef, pszBuf, cbBuf, kCFStringEncodingUTF8); if (fRc) rc = VINF_SUCCESS; else { CFIndex cwc = CFStringGetLength(StringRef); size_t cbTmp = cwc + 1; char *pszTmp = (char *)RTMemTmpAlloc(cbTmp); int cTries = 1; while ( pszTmp && (fRc = CFStringGetCString(StringRef, pszTmp, cbTmp, kCFStringEncodingUTF8)) == FALSE && cTries++ < 4) { RTMemTmpFree(pszTmp); cbTmp *= 2; pszTmp = (char *)RTMemTmpAlloc(cbTmp); } if (fRc) rc = RTStrCopy(pszBuf, cbBuf, pszTmp); else if (!pszTmp) rc = VERR_NO_TMP_MEMORY; else rc = VERR_ACCESS_DENIED; RTMemFree(pszTmp); } CFRelease(StringRef); break; } } } IOObjectRelease(ServiceObject); IOObjectRelease(Iterator); return rc; }
/** * @callback_method_impl{dtrace_pops_t,dtps_provide} */ static void vboxDtPOps_Provide(void *pvProv, const dtrace_probedesc_t *pDtProbeDesc) { PSUPDRVVDTPROVIDERCORE pProv = (PSUPDRVVDTPROVIDERCORE)pvProv; AssertPtrReturnVoid(pProv); LOG_DTRACE(("%s: %p / %p pDtProbeDesc=%p\n", __FUNCTION__, pProv, pProv->TracerData.DTrace.idProvider, pDtProbeDesc)); if (pDtProbeDesc) return; /* We don't generate probes, so never mind these requests. */ if (pProv->TracerData.DTrace.fZombie) return; dtrace_provider_id_t const idProvider = pProv->TracerData.DTrace.idProvider; AssertPtrReturnVoid(idProvider); AssertPtrReturnVoid(pProv->pHdr); AssertReturnVoid(pProv->pHdr->offProbeLocs != 0); uint32_t const cProbeLocs = pProv->pHdr->cbProbeLocs / sizeof(VTGPROBELOC); /* Need a buffer for extracting the function names and mangling them in case of collision. */ size_t const cbFnNmBuf = _4K + _1K; char *pszFnNmBuf = (char *)RTMemAlloc(cbFnNmBuf); if (!pszFnNmBuf) return; /* * Itereate the probe location list and register all probes related to * this provider. */ uint16_t const idxProv = (uint16_t)((PVTGDESCPROVIDER)((uintptr_t)pProv->pHdr + pProv->pHdr->offProviders) - pProv->pDesc); uint32_t idxProbeLoc; for (idxProbeLoc = 0; idxProbeLoc < cProbeLocs; idxProbeLoc++) { /* Skip probe location belonging to other providers or once that we've already reported. */ PCVTGPROBELOC pProbeLocRO = &pProv->paProbeLocsRO[idxProbeLoc]; PVTGDESCPROBE pProbeDesc = pProbeLocRO->pProbe; if (pProbeDesc->idxProvider != idxProv) continue; uint32_t *pidProbe; if (!pProv->fUmod) pidProbe = (uint32_t *)&pProbeLocRO->idProbe; else pidProbe = &pProv->paR0ProbeLocs[idxProbeLoc].idProbe; if (*pidProbe != 0) continue; /* The function name may need to be stripped since we're using C++ compilers for most of the code. ASSUMES nobody are brave/stupid enough to use function pointer returns without typedef'ing properly them (e.g. signal). */ const char *pszPrbName = vboxDtVtgGetString(pProv->pHdr, pProbeDesc->offName); const char *pszFunc = pProbeLocRO->pszFunction; const char *psz = strchr(pProbeLocRO->pszFunction, '('); size_t cch; if (psz) { /* skip blanks preceeding the parameter parenthesis. */ while ( (uintptr_t)psz > (uintptr_t)pProbeLocRO->pszFunction && RT_C_IS_BLANK(psz[-1])) psz--; /* Find the start of the function name. */ pszFunc = psz - 1; while ((uintptr_t)pszFunc > (uintptr_t)pProbeLocRO->pszFunction) { char ch = pszFunc[-1]; if (!RT_C_IS_ALNUM(ch) && ch != '_' && ch != ':') break; pszFunc--; } cch = psz - pszFunc; } else cch = strlen(pszFunc); RTStrCopyEx(pszFnNmBuf, cbFnNmBuf, pszFunc, cch); /* Look up the probe, if we have one in the same function, mangle the function name a little to avoid having to deal with having multiple location entries with the same probe ID. (lazy bird) */ Assert(!*pidProbe); if (dtrace_probe_lookup(idProvider, pProv->pszModName, pszFnNmBuf, pszPrbName) != DTRACE_IDNONE) { RTStrPrintf(pszFnNmBuf+cch, cbFnNmBuf - cch, "-%u", pProbeLocRO->uLine); if (dtrace_probe_lookup(idProvider, pProv->pszModName, pszFnNmBuf, pszPrbName) != DTRACE_IDNONE) { unsigned iOrd = 2; while (iOrd < 128) { RTStrPrintf(pszFnNmBuf+cch, cbFnNmBuf - cch, "-%u-%u", pProbeLocRO->uLine, iOrd); if (dtrace_probe_lookup(idProvider, pProv->pszModName, pszFnNmBuf, pszPrbName) == DTRACE_IDNONE) break; iOrd++; } if (iOrd >= 128) { LogRel(("VBoxDrv: More than 128 duplicate probe location instances %s at line %u in function %s [%s], probe %s\n", pProbeLocRO->uLine, pProbeLocRO->pszFunction, pszFnNmBuf, pszPrbName)); continue; } } } /* Create the probe. */ AssertCompile(sizeof(*pidProbe) == sizeof(dtrace_id_t)); *pidProbe = dtrace_probe_create(idProvider, pProv->pszModName, pszFnNmBuf, pszPrbName, 1 /*aframes*/, (void *)(uintptr_t)idxProbeLoc); pProv->TracerData.DTrace.cProvidedProbes++; } RTMemFree(pszFnNmBuf); LOG_DTRACE(("%s: returns\n", __FUNCTION__)); }
/** @copydoc RTLDROPS::pfnEnumSegments. */ static DECLCALLBACK(int) rtkldr_EnumSegments(PRTLDRMODINTERNAL pMod, PFNRTLDRENUMSEGS pfnCallback, void *pvUser) { PRTLDRMODKLDR pThis = (PRTLDRMODKLDR)pMod; uint32_t const cSegments = pThis->pMod->cSegments; PCKLDRSEG paSegments = &pThis->pMod->aSegments[0]; char szName[128]; for (uint32_t iSeg = 0; iSeg < cSegments; iSeg++) { RTLDRSEG Seg; if (!paSegments[iSeg].cchName) { Seg.pszName = szName; Seg.cchName = (uint32_t)RTStrPrintf(szName, sizeof(szName), "Seg%02u", iSeg); } else if (paSegments[iSeg].pchName[paSegments[iSeg].cchName]) { AssertReturn(paSegments[iSeg].cchName < sizeof(szName), VERR_INTERNAL_ERROR_3); RTStrCopyEx(szName, sizeof(szName), paSegments[iSeg].pchName, paSegments[iSeg].cchName); Seg.pszName = szName; Seg.cchName = paSegments[iSeg].cchName; } else { Seg.pszName = paSegments[iSeg].pchName; Seg.cchName = paSegments[iSeg].cchName; } Seg.SelFlat = paSegments[iSeg].SelFlat; Seg.Sel16bit = paSegments[iSeg].Sel16bit; Seg.fFlags = paSegments[iSeg].fFlags; AssertCompile(KLDRSEG_FLAG_16BIT == RTLDRSEG_FLAG_16BIT ); AssertCompile(KLDRSEG_FLAG_OS2_ALIAS16 == RTLDRSEG_FLAG_OS2_ALIAS16); AssertCompile(KLDRSEG_FLAG_OS2_CONFORM == RTLDRSEG_FLAG_OS2_CONFORM); AssertCompile(KLDRSEG_FLAG_OS2_IOPL == RTLDRSEG_FLAG_OS2_IOPL ); switch (paSegments[iSeg].enmProt) { default: AssertMsgFailed(("%d\n", paSegments[iSeg].enmProt)); case KPROT_NOACCESS: Seg.fProt = 0; break; case KPROT_READONLY: Seg.fProt = RTMEM_PROT_READ; break; case KPROT_READWRITE: Seg.fProt = RTMEM_PROT_READ | RTMEM_PROT_WRITE; break; case KPROT_WRITECOPY: Seg.fProt = RTMEM_PROT_WRITE; break; case KPROT_EXECUTE: Seg.fProt = RTMEM_PROT_EXEC; break; case KPROT_EXECUTE_READ: Seg.fProt = RTMEM_PROT_EXEC | RTMEM_PROT_READ; break; case KPROT_EXECUTE_READWRITE: Seg.fProt = RTMEM_PROT_EXEC | RTMEM_PROT_READ | RTMEM_PROT_WRITE; break; case KPROT_EXECUTE_WRITECOPY: Seg.fProt = RTMEM_PROT_EXEC | RTMEM_PROT_WRITE; break; } Seg.cb = paSegments[iSeg].cb; Seg.Alignment = paSegments[iSeg].Alignment; Seg.LinkAddress = paSegments[iSeg].LinkAddress; Seg.offFile = paSegments[iSeg].offFile; Seg.cbFile = paSegments[iSeg].cbFile; Seg.RVA = paSegments[iSeg].RVA; Seg.cbMapped = paSegments[iSeg].cbMapped; int rc = pfnCallback(pMod, &Seg, pvUser); if (rc != VINF_SUCCESS) return rc; } return VINF_SUCCESS; }
/** * Get Parallel port address and update the shared data * structure. * @returns VBox status code. * @param pThis The host parallel port instance data. */ static int drvWinHostGetparportAddr(PDRVHOSTPARALLEL pThis) { HDEVINFO hDevInfo; SP_DEVINFO_DATA DeviceInfoData; uint32_t u32Idx; uint32_t u32ParportAddr; int rc = VINF_SUCCESS; hDevInfo = SetupDiGetClassDevs(NULL, 0, 0, DIGCF_PRESENT | DIGCF_ALLCLASSES); if (hDevInfo == INVALID_HANDLE_VALUE) return VERR_INVALID_HANDLE; /* Enumerate through all devices in Set. */ DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); for (u32Idx = 0; SetupDiEnumDeviceInfo(hDevInfo, u32Idx, &DeviceInfoData); u32Idx++) { DWORD dwDataType; uint8_t *pBuf = NULL; DWORD dwBufSize = 0; while (!SetupDiGetDeviceRegistryProperty(hDevInfo, &DeviceInfoData, SPDRP_FRIENDLYNAME, (PDWORD)&dwDataType, (uint8_t *)pBuf, dwBufSize, (PDWORD)&dwBufSize)) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { LogFlow(("ERROR_INSUFF_BUFF = %d. dwBufSz = %d\n", GetLastError(), dwBufSize)); if (pBuf) RTMemFree(pBuf); pBuf = (uint8_t *)RTMemAlloc(dwBufSize * 2); } else { /* No need to bother about this error (in most cases its errno=13, * INVALID_DATA . Just break from here and proceed to next device * enumerated item */ LogFlow(("GetDevProp Error = %d & dwBufSz = %d\n", GetLastError(), dwBufSize)); break; } } if (RTStrStr((char*)pBuf, "LPT")) { u32ParportAddr = drvHostWinFindIORangeResource(DeviceInfoData.DevInst); if (u32ParportAddr) { /* Find parallel port name and update the shared data struncture */ char *pCh = RTStrStr((char*)pBuf, "("); char *pTmpCh = RTStrStr((char *)pBuf, ")"); /* check for the confirmation for the availability of parallel port */ if (!(pCh && pTmpCh)) { LogFlowFunc(("Parallel port Not Found. \n")); return VERR_NOT_FOUND; } if (((pTmpCh - (char *)pBuf) - (pCh - (char *)pBuf)) < 0) { LogFlowFunc(("Parallel port string not properly formatted.\n")); return VERR_NOT_FOUND; } /* check for the confirmation for the availability of parallel port */ if (RTStrCopyEx((char *)(pThis->szParportName), sizeof(pThis->szParportName), pCh+1, ((pTmpCh - (char *)pBuf) - (pCh - (char *)pBuf)) - 1)) { LogFlowFunc(("Parallel Port Not Found.\n")); return VERR_NOT_FOUND; } *((char *)pThis->szParportName + (pTmpCh - (char *)pBuf) - (pCh - (char *)pBuf) + 1 ) = '\0'; /* checking again to make sure that we have got a valid name and in valid format too. */ if (RTStrNCmp((char *)pThis->szParportName, "LPT", 3)) { LogFlowFunc(("Parallel Port name \"LPT\" Not Found.\n")); return VERR_NOT_FOUND; } if (!RTStrStr((char *)pThis->szParportName, "LPT") || !(pThis->szParportName[3] >= '0' && pThis->szParportName[3] <= '9')) { RT_BZERO(pThis->szParportName, sizeof(pThis->szParportName)); LogFlowFunc(("Printer Port Name Not Found.\n")); return VERR_NOT_FOUND; } pThis->fParportAvail = true; pThis->u32LptAddr = u32ParportAddr; pThis->u32LptAddrControl = pThis->u32LptAddr + CTRL_REG_OFFSET; pThis->u32LptAddrStatus = pThis->u32LptAddr + STATUS_REG_OFFSET; } else LogFlowFunc(("u32Parport Addr No Available \n")); if (pThis->fParportAvail) break; } if (pBuf) RTMemFree(pBuf); if (pThis->fParportAvail) { /* Parallel port address has been found. No need to iterate further. */ break; } } if (GetLastError() != NO_ERROR && GetLastError() != ERROR_NO_MORE_ITEMS) rc = VERR_GENERAL_FAILURE; SetupDiDestroyDeviceInfoList(hDevInfo); return rc; }
/** * Parses and validates the first TAR header of a archive/file/dir/whatever. * * @returns IPRT status code. * @param pThis The TAR reader stat. * @param pTar The TAR header that has been read. * @param fFirst Set if this is the first header, otherwise * clear. */ static int rtZipTarReaderParseNextHeader(PRTZIPTARREADER pThis, PCRTZIPTARHDR pHdr, bool fFirst) { int rc; /* * Basic header validation and detection first. */ RTZIPTARTYPE enmType; rc = rtZipTarHdrValidate(pHdr, &enmType); if (RT_FAILURE_NP(rc)) { if (rc == VERR_TAR_ZERO_HEADER) { pThis->cZeroHdrs = 1; pThis->enmState = RTZIPTARREADERSTATE_ZERO; return VINF_SUCCESS; } return rc; } if (fFirst) pThis->enmType = enmType; /* * Handle the header by type. */ switch (pHdr->Common.typeflag) { case RTZIPTAR_TF_OLDNORMAL: case RTZIPTAR_TF_NORMAL: case RTZIPTAR_TF_CONTIG: case RTZIPTAR_TF_LINK: case RTZIPTAR_TF_SYMLINK: case RTZIPTAR_TF_CHR: case RTZIPTAR_TF_BLK: case RTZIPTAR_TF_FIFO: case RTZIPTAR_TF_DIR: /* * Extract the name first. */ if (!pHdr->Common.name[0]) return VERR_TAR_EMPTY_NAME; if (pThis->enmType == RTZIPTARTYPE_POSIX) { Assert(pThis->offGnuLongCur == 0); Assert(pThis->szName[0] == '\0'); pThis->szName[0] = '\0'; if (pHdr->Posix.prefix[0]) { rc = RTStrCopyEx(pThis->szName, sizeof(pThis->szName), pHdr->Posix.prefix, sizeof(pHdr->Posix.prefix)); AssertRC(rc); /* shall not fail */ rc = RTStrCat(pThis->szName, sizeof(pThis->szName), "/"); AssertRC(rc); /* ditto */ } rc = RTStrCatEx(pThis->szName, sizeof(pThis->szName), pHdr->Common.name, sizeof(pHdr->Common.name)); AssertRCReturn(rc, rc); } else if (pThis->enmType == RTZIPTARTYPE_GNU) { if (!pThis->szName[0]) { rc = RTStrCopyEx(pThis->szName, sizeof(pThis->szName), pHdr->Common.name, sizeof(pHdr->Common.name)); AssertRCReturn(rc, rc); } } else { /* Old TAR */ Assert(pThis->offGnuLongCur == 0); Assert(pThis->szName[0] == '\0'); rc = RTStrCopyEx(pThis->szName, sizeof(pThis->szName), pHdr->Common.name, sizeof(pHdr->Common.name)); AssertRCReturn(rc, rc); } /* * Extract the link target. */ if ( pHdr->Common.typeflag == RTZIPTAR_TF_LINK || pHdr->Common.typeflag == RTZIPTAR_TF_SYMLINK) { if ( pThis->enmType == RTZIPTARTYPE_POSIX || pThis->enmType == RTZIPTARTYPE_ANCIENT || (pThis->enmType == RTZIPTARTYPE_GNU && pThis->szTarget[0] == '\0') ) { Assert(pThis->szTarget[0] == '\0'); rc = RTStrCopyEx(pThis->szTarget, sizeof(pThis->szTarget), pHdr->Common.linkname, sizeof(pHdr->Common.linkname)); AssertRCReturn(rc, rc); } } else pThis->szTarget[0] = '\0'; pThis->Hdr = *pHdr; break; case RTZIPTAR_TF_X_HDR: case RTZIPTAR_TF_X_GLOBAL: /** @todo implement PAX */ return VERR_TAR_UNSUPPORTED_PAX_TYPE; case RTZIPTAR_TF_SOLARIS_XHDR: /** @todo implement solaris / pax attribute lists. */ return VERR_TAR_UNSUPPORTED_SOLARIS_HDR_TYPE; /* * A GNU long name or long link is a dummy record followed by one or * more 512 byte string blocks holding the long name/link. The name * lenght is encoded in the size field, null terminator included. If * it is a symlink or hard link the long name may be followed by a * long link sequence. */ case RTZIPTAR_TF_GNU_LONGNAME: case RTZIPTAR_TF_GNU_LONGLINK: { if (strcmp(pHdr->Gnu.name, "././@LongLink")) return VERR_TAR_MALFORMED_GNU_LONGXXXX; int64_t cb64; rc = rtZipTarHdrFieldToNum(pHdr->Gnu.size, sizeof(pHdr->Gnu.size), false /*fOctalOnly*/, &cb64); if (RT_FAILURE(rc) || cb64 < 0 || cb64 > _1M) return VERR_TAR_MALFORMED_GNU_LONGXXXX; uint32_t cb = (uint32_t)cb64; if (cb >= sizeof(pThis->szName)) return VERR_TAR_NAME_TOO_LONG; pThis->cbGnuLongExpect = cb; pThis->offGnuLongCur = 0; pThis->enmState = pHdr->Common.typeflag == RTZIPTAR_TF_GNU_LONGNAME ? RTZIPTARREADERSTATE_GNU_LONGNAME : RTZIPTARREADERSTATE_GNU_LONGLINK; break; } case RTZIPTAR_TF_GNU_DUMPDIR: case RTZIPTAR_TF_GNU_MULTIVOL: case RTZIPTAR_TF_GNU_SPARSE: case RTZIPTAR_TF_GNU_VOLDHR: /** @todo Implement or skip GNU headers */ return VERR_TAR_UNSUPPORTED_GNU_HDR_TYPE; default: return VERR_TAR_UNKNOWN_TYPE_FLAG; } return VINF_SUCCESS; }