RTDECL(char *) RTUriParsedScheme(const char *pszUri, PCRTURIPARSED pParsed) { AssertPtrReturn(pszUri, NULL); AssertPtrReturn(pParsed, NULL); AssertReturn(pParsed->u32Magic == RTURIPARSED_MAGIC, NULL); return RTStrDupN(pszUri, pParsed->cchScheme); }
static char *rtUriPercentDecodeN(const char *pszString, size_t cchMax) { if (!pszString) return NULL; int rc = VINF_SUCCESS; size_t cbLen = RT_MIN(strlen(pszString), cchMax); /* The new string can only get smaller. */ char *pszNew = (char*)RTMemAlloc(cbLen + 1); if (!pszNew) return NULL; char *pszRes = NULL; size_t iIn = 0; size_t iOut = 0; while(iIn < cbLen) { if (pszString[iIn] == '%') { /* % encoding means the percent sign and exactly 2 hexadecimal * digits describing the ASCII number of the character. */ ++iIn; char szNum[3]; szNum[0] = pszString[iIn++]; szNum[1] = pszString[iIn++]; szNum[2] = '\0'; uint8_t u8; rc = RTStrToUInt8Ex(szNum, NULL, 16, &u8); if (RT_FAILURE(rc)) break; pszNew[iOut] = u8; } else pszNew[iOut] = pszString[iIn++]; ++iOut; } if (RT_SUCCESS(rc)) { pszNew[iOut] = '\0'; if (iOut != iIn) { /* If the source and target strings have different size, recreate * the target string with the correct size. */ pszRes = RTStrDupN(pszNew, iOut); RTStrFree(pszNew); } else pszRes = pszNew; } else RTStrFree(pszNew); return pszRes; }
static char *rtUriPercentEncodeN(const char *pszString, size_t cchMax) { if (!pszString) return NULL; int rc = VINF_SUCCESS; size_t cbLen = RT_MIN(strlen(pszString), cchMax); /* The new string can be max 3 times in size of the original string. */ char *pszNew = RTStrAlloc(cbLen * 3 + 1); if (!pszNew) return NULL; char *pszRes = NULL; size_t iIn = 0; size_t iOut = 0; while (iIn < cbLen) { if (URI_EXCLUDED(pszString[iIn])) { char szNum[3] = { 0, 0, 0 }; RTStrFormatU8(&szNum[0], 3, pszString[iIn++], 16, 2, 2, RTSTR_F_CAPITAL | RTSTR_F_ZEROPAD); pszNew[iOut++] = '%'; pszNew[iOut++] = szNum[0]; pszNew[iOut++] = szNum[1]; } else pszNew[iOut++] = pszString[iIn++]; } if (RT_SUCCESS(rc)) { pszNew[iOut] = '\0'; if (iOut != iIn) { /* If the source and target strings have different size, recreate * the target string with the correct size. */ pszRes = RTStrDupN(pszNew, iOut); RTStrFree(pszNew); } else pszRes = pszNew; } else RTStrFree(pszNew); return pszRes; }
/** * Basic API checks. * We'll return if any of these fails. */ static void tst1(void) { RTTestISub("Basics"); char *psz; int rc = VINF_SUCCESS; /* RTStrAlloc */ RTTESTI_CHECK(psz = RTStrAlloc(0)); RTTESTI_CHECK(psz && !*psz); RTStrFree(psz); RTTESTI_CHECK(psz = RTStrAlloc(1)); RTTESTI_CHECK(psz && !*psz); RTStrFree(psz); RTTESTI_CHECK(psz = RTStrAlloc(128)); RTTESTI_CHECK(psz && !*psz); RTStrFree(psz); /* RTStrAllocEx */ psz = (char*)"asdfasdf"; RTTESTI_CHECK_RC(RTStrAllocEx(&psz, 0), VINF_SUCCESS); RTTESTI_CHECK(psz && !*psz); RTStrFree(psz); RTTESTI_CHECK_RC(RTStrAllocEx(&psz, 1), VINF_SUCCESS); RTTESTI_CHECK(psz && !*psz); RTStrFree(psz); RTTESTI_CHECK_RC(RTStrAllocEx(&psz, 128), VINF_SUCCESS); RTTESTI_CHECK(psz && !*psz); RTStrFree(psz); /* RTStrRealloc */ psz = NULL; RTTESTI_CHECK_RC(RTStrRealloc(&psz, 10), VINF_SUCCESS); RTTESTI_CHECK(psz && !psz[0]); RTTESTI_CHECK(psz && !psz[9]); RTStrFree(psz); psz = NULL; RTTESTI_CHECK_RC(RTStrRealloc(&psz, 0), VINF_SUCCESS); RTTESTI_CHECK(!psz); psz = NULL; RTTESTI_CHECK_RC(RTStrRealloc(&psz, 128), VINF_SUCCESS); RTTESTI_CHECK(psz && !psz[0]); RTTESTI_CHECK(psz && !psz[127]); if (psz) { memset(psz, 'a', 127); RTTESTI_CHECK_RC(rc = RTStrRealloc(&psz, 160), VINF_SUCCESS); if (RT_SUCCESS(rc) && psz) { RTTESTI_CHECK(!psz[127]); RTTESTI_CHECK(!psz[159]); RTTESTI_CHECK(ASMMemIsAll8(psz, 127, 'a') == NULL); memset(psz, 'b', 159); RTTESTI_CHECK_RC(rc = RTStrRealloc(&psz, 79), VINF_SUCCESS); if (RT_SUCCESS(rc)) { RTTESTI_CHECK(!psz[78]); RTTESTI_CHECK(ASMMemIsAll8(psz, 78, 'b') == NULL); RTTESTI_CHECK_RC(rc = RTStrRealloc(&psz, 0), VINF_SUCCESS); RTTESTI_CHECK(!psz); } } } RTStrFree(psz); /* RTStrDup */ RTTESTI_CHECK(psz = RTStrDup("")); RTTESTI_CHECK(psz && *psz == '\0'); RTStrFree(psz); RTTESTI_CHECK(psz = RTStrDup("abcdefghijklmnop")); RTTESTI_CHECK(!RTStrCmp(psz, "abcdefghijklmnop")); RTStrFree(psz); /* RTStrDupEx */ psz = NULL; RTTESTI_CHECK_RC(RTStrDupEx(&psz, ""), VINF_SUCCESS); RTTESTI_CHECK(RT_FAILURE(rc) || *psz == '\0'); if (RT_SUCCESS(rc)) RTStrFree(psz); psz = (char*)"asdfasdfasdfasdf"; RTTESTI_CHECK_RC(rc = RTStrDupEx(&psz, "abcdefghijklmnop"), VINF_SUCCESS); RTTESTI_CHECK(RT_FAILURE(rc) || !RTStrCmp(psz, "abcdefghijklmnop")); if (RT_SUCCESS(rc)) RTStrFree(psz); /* RTStrDupN */ RTTESTI_CHECK(psz = RTStrDupN("abcdefg", 3)); RTTESTI_CHECK(!RTStrCmp(psz, "abc")); RTStrFree(psz); RTTESTI_CHECK(psz = RTStrDupN("abc", 100000)); RTTESTI_CHECK(!RTStrCmp(psz, "abc")); RTStrFree(psz); RTTESTI_CHECK(psz = RTStrDupN("abc", 0)); RTTESTI_CHECK(psz && *psz == '\0'); RTStrFree(psz); /* RTStrAAppend */ RTTESTI_CHECK(psz = RTStrDup("abc")); RTTESTI_CHECK_RC(RTStrAAppend(&psz, "def"), VINF_SUCCESS); RTTESTI_CHECK(!RTStrCmp(psz, "abcdef")); RTStrFree(psz); RTTESTI_CHECK(psz = RTStrDup("abc")); RTTESTI_CHECK_RC(RTStrAAppend(&psz, ""), VINF_SUCCESS); RTTESTI_CHECK(!RTStrCmp(psz, "abc")); RTTESTI_CHECK_RC(RTStrAAppend(&psz, NULL), VINF_SUCCESS); RTTESTI_CHECK(!RTStrCmp(psz, "abc")); RTStrFree(psz); psz = NULL; RTTESTI_CHECK_RC(RTStrAAppend(&psz, "xyz"), VINF_SUCCESS); RTTESTI_CHECK(!RTStrCmp(psz, "xyz")); RTStrFree(psz); /* RTStrAAppendN */ RTTESTI_CHECK(psz = RTStrDup("abc")); RTTESTI_CHECK_RC(RTStrAAppendN(&psz, "def", 1), VINF_SUCCESS); RTTESTI_CHECK(!RTStrCmp(psz, "abcd")); RTStrFree(psz); RTTESTI_CHECK(psz = RTStrDup("abc")); RTTESTI_CHECK_RC(RTStrAAppendN(&psz, "", 0), VINF_SUCCESS); RTTESTI_CHECK(!RTStrCmp(psz, "abc")); RTTESTI_CHECK_RC(RTStrAAppendN(&psz, "", RTSTR_MAX), VINF_SUCCESS); RTTESTI_CHECK(!RTStrCmp(psz, "abc")); RTTESTI_CHECK_RC(RTStrAAppendN(&psz, NULL, 0), VINF_SUCCESS); RTTESTI_CHECK(!RTStrCmp(psz, "abc")); RTStrFree(psz); psz = NULL; RTTESTI_CHECK_RC(RTStrAAppendN(&psz, "abc", 2), VINF_SUCCESS); RTTESTI_CHECK(!RTStrCmp(psz, "ab")); RTTESTI_CHECK_RC(RTStrAAppendN(&psz, "cdefghijklm", 1), VINF_SUCCESS); RTTESTI_CHECK(!RTStrCmp(psz, "abc")); RTTESTI_CHECK_RC(RTStrAAppendN(&psz, "defghijklm", RTSTR_MAX), VINF_SUCCESS); RTTESTI_CHECK(!RTStrCmp(psz, "abcdefghijklm")); RTStrFree(psz); /* RTStrAAppendExN / RTStrAAppendExNV */ psz = NULL; RTTESTI_CHECK_RC(RTStrAAppendExN(&psz, 5, "a", (size_t)1, "bc", (size_t)1, "cdefg", RTSTR_MAX, "hijkl", (size_t)2, "jklmnopqrstuvwxyz", RTSTR_MAX), VINF_SUCCESS); RTTESTI_CHECK(!RTStrCmp(psz, "abcdefghijklmnopqrstuvwxyz")); RTTESTI_CHECK_RC(RTStrAAppendExN(&psz, 0), VINF_SUCCESS); RTTESTI_CHECK(!RTStrCmp(psz, "abcdefghijklmnopqrstuvwxyz")); RTTESTI_CHECK_RC(RTStrAAppendExN(&psz, 2, NULL, (size_t)0, "", (size_t)0), VINF_SUCCESS); RTTESTI_CHECK(!RTStrCmp(psz, "abcdefghijklmnopqrstuvwxyz")); RTTESTI_CHECK_RC(RTStrAAppendExN(&psz, 1, "-", (size_t)1), VINF_SUCCESS); RTTESTI_CHECK(!RTStrCmp(psz, "abcdefghijklmnopqrstuvwxyz-")); RTStrFree(psz); /* RTStrATruncate */ psz = NULL; RTTESTI_CHECK_RC(RTStrATruncate(&psz, 0), VINF_SUCCESS); RTTESTI_CHECK(!psz); RTTESTI_CHECK(psz = RTStrDup("")); RTTESTI_CHECK_RC(RTStrATruncate(&psz, 0), VINF_SUCCESS); RTStrFree(psz); RTTESTI_CHECK(psz = RTStrDup("1234567890")); RTTESTI_CHECK_RC(RTStrATruncate(&psz, 5), VINF_SUCCESS); RTTESTI_CHECK(!RTStrCmp(psz, "12345")); RTStrFree(psz); psz = NULL; for (uint32_t i = 0; i < 128; i++) RTTESTI_CHECK_RC_RETV(RTStrAAppend(&psz, "abcdefghijklmnopqrstuvwxyz"), VINF_SUCCESS); RTTESTI_CHECK_RC(RTStrATruncate(&psz, sizeof("abcdefghijklmnopqrstuvwxyz") - 1), VINF_SUCCESS); RTTESTI_CHECK(!RTStrCmp(psz, "abcdefghijklmnopqrstuvwxyz")); RTTESTI_CHECK_RC(RTStrATruncate(&psz, 6), VINF_SUCCESS); RTTESTI_CHECK(!RTStrCmp(psz, "abcdef")); RTTESTI_CHECK_RC(RTStrATruncate(&psz, 1), VINF_SUCCESS); RTTESTI_CHECK(!RTStrCmp(psz, "a")); RTTESTI_CHECK_RC(RTStrATruncate(&psz, 0), VINF_SUCCESS); RTTESTI_CHECK(!RTStrCmp(psz, "")); RTStrFree(psz); }
static int vbglR3DnDHGProcessURIMessages(uint32_t uClientId, uint32_t *puScreenId, char *pszFormat, uint32_t cbFormat, uint32_t *pcbFormatRecv, void **ppvData, uint32_t cbData, size_t *pcbDataRecv) { /* Make a string list out of the uri data. */ RTCList<RTCString> uriList = RTCString(static_cast<char*>(*ppvData), *pcbDataRecv - 1).split("\r\n"); if (uriList.isEmpty()) return VINF_SUCCESS; uint32_t cbTmpData = _1M * 10; void *pvTmpData = RTMemAlloc(cbTmpData); if (!pvTmpData) return VERR_NO_MEMORY; /* Create and query the drop target directory. */ char pszDropDir[RTPATH_MAX]; int rc = vbglR3DnDCreateDropDir(pszDropDir, sizeof(pszDropDir)); if (RT_FAILURE(rc)) { RTMemFree(pvTmpData); return rc; } /* Patch the old drop data with the new drop directory, so the drop target * can find the files. */ RTCList<RTCString> guestUriList; for (size_t i = 0; i < uriList.size(); ++i) { const RTCString &strUri = uriList.at(i); /* Query the path component of a file URI. If this hasn't a * file scheme, null is returned. */ if (char *pszFilePath = RTUriFilePath(strUri.c_str(), URI_FILE_FORMAT_AUTO)) { RTCString strFullPath = RTCString().printf("%s%c%s", pszDropDir, RTPATH_SLASH, pszFilePath); char *pszNewUri = RTUriFileCreate(strFullPath.c_str()); if (pszNewUri) { guestUriList.append(pszNewUri); RTStrFree(pszNewUri); } } else guestUriList.append(strUri); } /* Cleanup the old data and write the new data back to the event. */ RTMemFree(*ppvData); RTCString newData = RTCString::join(guestUriList, "\r\n") + "\r\n"; *ppvData = RTStrDupN(newData.c_str(), newData.length()); *pcbDataRecv = newData.length() + 1; /* Lists for holding created files & directories in the case of a * rollback. */ RTCList<RTCString> guestDirList; RTCList<RTCString> guestFileList; char pszPathname[RTPATH_MAX]; uint32_t cbPathname = 0; bool fLoop = true; do { uint32_t uNextMsg; uint32_t cNextParms; rc = vbglR3DnDQueryNextHostMessageType(uClientId, &uNextMsg, &cNextParms, false); DO(("%Rrc - %d\n", rc , uNextMsg)); if (RT_SUCCESS(rc)) { switch(uNextMsg) { case DragAndDropSvc::HOST_DND_HG_SND_DIR: { uint32_t fMode = 0; rc = vbglR3DnDHGProcessSendDirMessage(uClientId, pszPathname, sizeof(pszPathname), &cbPathname, &fMode); if (RT_SUCCESS(rc)) { DO(("Got drop dir: %s - %o - %Rrc\n", pszPathname, fMode, rc)); char *pszNewDir = RTPathJoinA(pszDropDir, pszPathname); rc = RTDirCreate(pszNewDir, (fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRWXU, 0); if (!guestDirList.contains(pszNewDir)) guestDirList.append(pszNewDir); } break; } case DragAndDropSvc::HOST_DND_HG_SND_FILE: { uint32_t cbDataRecv; uint32_t fMode = 0; rc = vbglR3DnDHGProcessSendFileMessage(uClientId, pszPathname, sizeof(pszPathname), &cbPathname, pvTmpData, cbTmpData, &cbDataRecv, &fMode); if (RT_SUCCESS(rc)) { char *pszNewFile = RTPathJoinA(pszDropDir, pszPathname); DO(("Got drop file: %s - %d - %o - %Rrc\n", pszPathname, cbDataRecv, fMode, rc)); RTFILE hFile; rc = RTFileOpen(&hFile, pszNewFile, RTFILE_O_WRITE | RTFILE_O_APPEND | RTFILE_O_DENY_ALL | RTFILE_O_OPEN_CREATE); if (RT_SUCCESS(rc)) { rc = RTFileSeek(hFile, 0, RTFILE_SEEK_END, NULL); if (RT_SUCCESS(rc)) { rc = RTFileWrite(hFile, pvTmpData, cbDataRecv, 0); /* Valid UNIX mode? */ if ( RT_SUCCESS(rc) && (fMode & RTFS_UNIX_MASK)) rc = RTFileSetMode(hFile, (fMode & RTFS_UNIX_MASK) | RTFS_UNIX_IRUSR | RTFS_UNIX_IWUSR); } RTFileClose(hFile); if (!guestFileList.contains(pszNewFile)) guestFileList.append(pszNewFile); } } break; } case DragAndDropSvc::HOST_DND_HG_EVT_CANCEL: { rc = vbglR3DnDHGProcessCancelMessage(uClientId); if (RT_SUCCESS(rc)) rc = VERR_CANCELLED; /* Break out of the loop. */ } default: fLoop = false; break; } } else { if (rc == VERR_NO_DATA) rc = VINF_SUCCESS; break; } }while(fLoop); RTMemFree(pvTmpData); /* Cleanup on failure or if the user has canceled. */ if (RT_FAILURE(rc)) { /* Remove any stuff created. */ for (size_t i = 0; i < guestFileList.size(); ++i) RTFileDelete(guestFileList.at(i).c_str()); for (size_t i = 0; i < guestDirList.size(); ++i) RTDirRemove(guestDirList.at(i).c_str()); RTDirRemove(pszDropDir); } return rc; }
PUSBDEVICE USBProxyBackendFreeBSD::getDevices(void) { PUSBDEVICE pDevices = NULL; int FileUsb = 0; int iBus = 0; int iAddr = 1; int rc = VINF_SUCCESS; char *pszDevicePath = NULL; uint32_t PlugTime = 0; for (;;) { rc = RTStrAPrintf(&pszDevicePath, "/dev/%s%d.%d", USB_GENERIC_NAME, iBus, iAddr); if (RT_FAILURE(rc)) { mLastError = rc; break; } LogFlowFunc((": Opening %s\n", pszDevicePath)); FileUsb = open(pszDevicePath, O_RDONLY); if (FileUsb < 0) { if ( (errno != ENOENT) && (errno != EACCES)) mLastError = RTErrConvertFromErrno(errno); RTStrFree(pszDevicePath); if ((errno == ENOENT) && (iAddr > 1)) { iAddr = 1; iBus++; continue; } else if (errno == EACCES) { /* Skip devices without the right permission. */ iAddr++; continue; } else break; } LogFlowFunc((": %s opened successfully\n", pszDevicePath)); struct usb_device_info UsbDevInfo; RT_ZERO(UsbDevInfo); rc = ioctl(FileUsb, USB_GET_DEVICEINFO, &UsbDevInfo); if (rc < 0) { LogFlowFunc((": Error querying device info rc=%Rrc\n", RTErrConvertFromErrno(errno))); mLastError = RTErrConvertFromErrno(errno); close(FileUsb); RTStrFree(pszDevicePath); break; } /* Filter out hubs */ if (UsbDevInfo.udi_class != 0x09) { PUSBDEVICE pDevice = (PUSBDEVICE)RTMemAllocZ(sizeof(USBDEVICE)); if (!pDevice) { mLastError = VERR_NO_MEMORY; close(FileUsb); RTStrFree(pszDevicePath); break; } pDevice->enmState = USBDEVICESTATE_UNUSED; pDevice->bBus = UsbDevInfo.udi_bus; pDevice->bDeviceClass = UsbDevInfo.udi_class; pDevice->bDeviceSubClass = UsbDevInfo.udi_subclass; pDevice->bDeviceProtocol = UsbDevInfo.udi_protocol; pDevice->bNumConfigurations = UsbDevInfo.udi_config_no; pDevice->idVendor = UsbDevInfo.udi_vendorNo; pDevice->idProduct = UsbDevInfo.udi_productNo; pDevice->bDevNum = UsbDevInfo.udi_index; switch (UsbDevInfo.udi_speed) { case USB_SPEED_LOW: pDevice->enmSpeed = USBDEVICESPEED_LOW; break; case USB_SPEED_FULL: pDevice->enmSpeed = USBDEVICESPEED_FULL; break; case USB_SPEED_HIGH: pDevice->enmSpeed = USBDEVICESPEED_HIGH; break; case USB_SPEED_SUPER: case USB_SPEED_VARIABLE: default: pDevice->enmSpeed = USBDEVICESPEED_UNKNOWN; } if (UsbDevInfo.udi_vendor[0] != '\0') pDevice->pszManufacturer = RTStrDupN(UsbDevInfo.udi_vendor, sizeof(UsbDevInfo.udi_vendor)); if (UsbDevInfo.udi_product[0] != '\0') pDevice->pszProduct = RTStrDupN(UsbDevInfo.udi_product, sizeof(UsbDevInfo.udi_product)); if (UsbDevInfo.udi_serial[0] != '\0') { pDevice->pszSerialNumber = RTStrDupN(UsbDevInfo.udi_serial, sizeof(UsbDevInfo.udi_serial)); pDevice->u64SerialHash = USBLibHashSerial(pDevice->pszSerialNumber); } rc = ioctl(FileUsb, USB_GET_PLUGTIME, &PlugTime); if (rc == 0) pDevice->u64SerialHash += PlugTime; pDevice->pszAddress = RTStrDup(pszDevicePath); pDevice->pszBackend = RTStrDup("host"); pDevice->enmState = USBDEVICESTATE_USED_BY_HOST_CAPTURABLE; usbLogDevice(pDevice); pDevice->pNext = pDevices; if (pDevices) pDevices->pPrev = pDevice; pDevices = pDevice; } close(FileUsb); RTStrFree(pszDevicePath); iAddr++; } return pDevices; }
/** * Internal write API, stream lock already held. * * @returns IPRT status code. * @param pStream The stream. * @param pvBuf What to write. * @param cbWrite How much to write. * @param pcbWritten Where to optionally return the number of bytes * written. * @param fSureIsText Set if we're sure this is UTF-8 text already. */ static int rtStrmWriteLocked(PRTSTREAM pStream, const void *pvBuf, size_t cbWrite, size_t *pcbWritten, bool fSureIsText) { int rc = pStream->i32Error; if (RT_FAILURE(rc)) return rc; if (pStream->fRecheckMode) rtStreamRecheckMode(pStream); #ifdef RT_OS_WINDOWS /* * Use the unicode console API when possible in order to avoid stuff * getting lost in unnecessary code page translations. */ HANDLE hCon; if (rtStrmIsConsoleUnlocked(pStream, &hCon)) { # ifdef HAVE_FWRITE_UNLOCKED if (!fflush_unlocked(pStream->pFile)) # else if (!fflush(pStream->pFile)) # endif { /** @todo Consider buffering later. For now, we'd rather correct output than * fast output. */ DWORD cwcWritten = 0; PRTUTF16 pwszSrc = NULL; size_t cwcSrc = 0; rc = RTStrToUtf16Ex((const char *)pvBuf, cbWrite, &pwszSrc, 0, &cwcSrc); if (RT_SUCCESS(rc)) { if (!WriteConsoleW(hCon, pwszSrc, (DWORD)cwcSrc, &cwcWritten, NULL)) { /* try write char-by-char to avoid heap problem. */ cwcWritten = 0; while (cwcWritten != cwcSrc) { DWORD cwcThis; if (!WriteConsoleW(hCon, &pwszSrc[cwcWritten], 1, &cwcThis, NULL)) { if (!pcbWritten || cwcWritten == 0) rc = RTErrConvertFromErrno(GetLastError()); break; } if (cwcThis != 1) /* Unable to write current char (amount)? */ break; cwcWritten++; } } if (RT_SUCCESS(rc)) { if (cwcWritten == cwcSrc) { if (pcbWritten) *pcbWritten = cbWrite; } else if (pcbWritten) { PCRTUTF16 pwszCur = pwszSrc; const char *pszCur = (const char *)pvBuf; while ((uintptr_t)(pwszCur - pwszSrc) < cwcWritten) { RTUNICP CpIgnored; RTUtf16GetCpEx(&pwszCur, &CpIgnored); RTStrGetCpEx(&pszCur, &CpIgnored); } *pcbWritten = pszCur - (const char *)pvBuf; } else rc = VERR_WRITE_ERROR; } RTUtf16Free(pwszSrc); } } else rc = RTErrConvertFromErrno(errno); if (RT_FAILURE(rc)) ASMAtomicWriteS32(&pStream->i32Error, rc); return rc; } #endif /* RT_OS_WINDOWS */ /* * If we're sure it's text output, convert it from UTF-8 to the current * code page before printing it. * * Note! Partial writes are not supported in this scenario because we * cannot easily report back a written length matching the input. */ /** @todo Skip this if the current code set is UTF-8. */ if ( pStream->fCurrentCodeSet && !pStream->fBinary && ( fSureIsText || rtStrmIsUtf8Text(pvBuf, cbWrite)) ) { char *pszSrcFree = NULL; const char *pszSrc = (const char *)pvBuf; if (pszSrc[cbWrite]) { pszSrc = pszSrcFree = RTStrDupN(pszSrc, cbWrite); if (pszSrc == NULL) rc = VERR_NO_STR_MEMORY; } if (RT_SUCCESS(rc)) { char *pszSrcCurCP; rc = RTStrUtf8ToCurrentCP(&pszSrcCurCP, pszSrc); if (RT_SUCCESS(rc)) { size_t cchSrcCurCP = strlen(pszSrcCurCP); IPRT_ALIGNMENT_CHECKS_DISABLE(); /* glibc / mempcpy again */ #ifdef HAVE_FWRITE_UNLOCKED ssize_t cbWritten = fwrite_unlocked(pszSrcCurCP, cchSrcCurCP, 1, pStream->pFile); #else ssize_t cbWritten = fwrite(pszSrcCurCP, cchSrcCurCP, 1, pStream->pFile); #endif IPRT_ALIGNMENT_CHECKS_ENABLE(); if (cbWritten == 1) { if (pcbWritten) *pcbWritten = cbWrite; } #ifdef HAVE_FWRITE_UNLOCKED else if (!ferror_unlocked(pStream->pFile)) #else else if (!ferror(pStream->pFile)) #endif { if (pcbWritten) *pcbWritten = 0; } else rc = VERR_WRITE_ERROR; RTStrFree(pszSrcCurCP); } RTStrFree(pszSrcFree); } if (RT_FAILURE(rc)) ASMAtomicWriteS32(&pStream->i32Error, rc); return rc; }
/** The actual implemenation code for @a createServiceFile. */ bool createServiceFileCore(char **ppachTemplate, struct SERVICEPARAMETERS *pParameters) { /* The size of the template data we have read. */ size_t cchTemplate = 0; /* The size of the buffer we have allocated. */ size_t cbBuffer = 0; /* How much of the template data we have written out. */ size_t cchWritten = 0; int rc = VINF_SUCCESS; /* First of all read in the file. */ while (rc != VINF_EOF) { size_t cchRead; if (cchTemplate == cbBuffer) { cbBuffer += READ_SIZE; *ppachTemplate = (char *)RTMemRealloc((void *)*ppachTemplate, cbBuffer); } if (!*ppachTemplate) { RTStrmPrintf(g_pStdErr, "Out of memory.\n"); return false; } rc = RTStrmReadEx(g_pStdIn, *ppachTemplate + cchTemplate, cbBuffer - cchTemplate, &cchRead); if (RT_FAILURE(rc)) { RTStrmPrintf(g_pStdErr, "Error reading input: %Rrc\n", rc); return false; } if (!cchRead) rc = VINF_EOF; cchTemplate += cchRead; } while (true) { /* Find the next '%' character if any and write out up to there (or the * end if there is no '%'). */ char *pchNext = (char *) memchr((void *)(*ppachTemplate + cchWritten), '%', cchTemplate - cchWritten); size_t cchToWrite = pchNext ? pchNext - *ppachTemplate - cchWritten : cchTemplate - cchWritten; rc = RTStrmWrite(g_pStdOut, *ppachTemplate + cchWritten, cchToWrite); if (RT_FAILURE(rc)) { RTStrmPrintf(g_pStdErr, "Error writing output: %Rrc\n", rc); return false; } cchWritten += cchToWrite; if (!pchNext) break; /* And substitute any of our well-known strings. We favour code * readability over efficiency here. */ if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, COMMAND, sizeof(COMMAND) - 1)) { if (!pParameters->pcszCommand) { RTStrmPrintf(g_pStdErr, "--command not specified.\n"); return false; } if (!writeCommand(pParameters->enmFormat, pParameters->pcszCommand)) return false; } else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, ARGUMENTS, sizeof(ARGUMENTS) - 1)) { if ( pParameters->pcszArguments && !writeQuoted(pParameters->enmFormat, pParameters->pcszArguments)) return false; } else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, DESCRIPTION, sizeof(DESCRIPTION) - 1)) { if (!pParameters->pcszDescription) { RTStrmPrintf(g_pStdErr, "--description not specified.\n"); return false; } if (!writePrintableString(pParameters->enmFormat, pParameters->pcszDescription)) return false; } else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, SERVICE_NAME, sizeof(SERVICE_NAME) - 1)) { if ( !pParameters->pcszCommand && !pParameters->pcszServiceName) { RTStrmPrintf(g_pStdErr, "Neither --command nor --service-name specified.\n"); return false; } if (pParameters->pcszServiceName) { if (!writePrintableString(pParameters->enmFormat, pParameters->pcszServiceName)) return false; } else { const char *pcszFileName = RTPathFilename(pParameters->pcszCommand); const char *pcszSuffix = RTPathSuffix(pParameters->pcszCommand); char *pszName = RTStrDupN(pcszFileName, pcszSuffix ? pcszSuffix - pcszFileName : RTPATH_MAX); bool fRc; if (!pszName) { RTStrmPrintf(g_pStdErr, "Out of memory.\n"); return false; } fRc = writePrintableString(pParameters->enmFormat, pszName); RTStrFree(pszName); if (!fRc) return false; } } else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, HAVE_ONESHOT, sizeof(HAVE_ONESHOT) - 1)) { if (!pParameters->fOneShot) skipLine(*ppachTemplate, cchTemplate, &cchWritten); } else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, HAVE_DAEMON, sizeof(HAVE_DAEMON) - 1)) { if (pParameters->fOneShot) skipLine(*ppachTemplate, cchTemplate, &cchWritten); } else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, STOP_COMMAND, sizeof(STOP_COMMAND) - 1)) { if ( pParameters->pcszStopCommand && !writeCommand(pParameters->enmFormat, pParameters->pcszStopCommand)) return false; } else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, STOP_ARGUMENTS, sizeof(STOP_ARGUMENTS) - 1)) { if ( pParameters->pcszStopArguments && !writeQuoted(pParameters->enmFormat, pParameters->pcszStopArguments)) return false; } else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, HAVE_STOP_COMMAND, sizeof(HAVE_STOP_COMMAND) - 1)) { if (!pParameters->pcszStopCommand) skipLine(*ppachTemplate, cchTemplate, &cchWritten); } else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, NO_STOP_COMMAND, sizeof(NO_STOP_COMMAND) - 1)) { if (pParameters->pcszStopCommand) skipLine(*ppachTemplate, cchTemplate, &cchWritten); } else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, STATUS_COMMAND, sizeof(STATUS_COMMAND) - 1)) { if ( pParameters->pcszStatusCommand && !writeCommand(pParameters->enmFormat, pParameters->pcszStatusCommand)) return false; } else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, STATUS_ARGUMENTS, sizeof(STATUS_ARGUMENTS) - 1)) { if ( pParameters->pcszStatusArguments && !writeQuoted(pParameters->enmFormat, pParameters->pcszStatusArguments)) return false; } else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, HAVE_STATUS_COMMAND, sizeof(HAVE_STATUS_COMMAND) - 1)) { if (!pParameters->pcszStatusCommand) skipLine(*ppachTemplate, cchTemplate, &cchWritten); } else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, NO_STATUS_COMMAND, sizeof(NO_STATUS_COMMAND) - 1)) { if (pParameters->pcszStatusCommand) skipLine(*ppachTemplate, cchTemplate, &cchWritten); } else if (getSequence(*ppachTemplate, cchTemplate, &cchWritten, "%%", 2)) { rc = RTStrmPutCh(g_pStdOut, '%'); if (RT_FAILURE(rc)) { RTStrmPrintf(g_pStdErr, "Error writing output: %Rrc\n", rc); return false; } } else { RTStrmPrintf(g_pStdErr, "Unknown substitution sequence in input at \"%.*s\"\n", RT_MIN(16, cchTemplate - cchWritten), *ppachTemplate + cchWritten); return false; } } return true; }