Пример #1
0
/**
 * Reads from a pipe.
 *
 * @returns @a rc or other status code.
 * @param   rc              The current status of the operation.  Error status
 *                          are preserved and returned.
 * @param   phPipeR         Pointer to the pipe handle.
 * @param   pcbAllocated    Pointer to the buffer size variable.
 * @param   poffCur         Pointer to the buffer offset variable.
 * @param   ppszBuffer      Pointer to the buffer pointer variable.
 */
static int rtProcProcessOutput(int rc, PRTPIPE phPipeR, size_t *pcbAllocated, size_t *poffCur, char **ppszBuffer,
                               RTPOLLSET hPollSet, uint32_t idPollSet)
{
    size_t  cbRead;
    char    szTmp[_4K - 1];
    for (;;)
    {
        int rc2 = RTPipeRead(*phPipeR, szTmp, sizeof(szTmp), &cbRead);
        if (RT_SUCCESS(rc2) && cbRead)
        {
            /* Resize the buffer. */
            if (*poffCur + cbRead >= *pcbAllocated)
            {
                if (*pcbAllocated >= _1G)
                {
                    RTPollSetRemove(hPollSet, idPollSet);
                    rc2 = RTPipeClose(*phPipeR); AssertRC(rc2);
                    *phPipeR = NIL_RTPIPE;
                    return RT_SUCCESS(rc) ? VERR_TOO_MUCH_DATA : rc;
                }

                size_t cbNew = *pcbAllocated ? *pcbAllocated * 2 : sizeof(szTmp) + 1;
                Assert(*poffCur + cbRead < cbNew);
                rc2 = RTStrRealloc(ppszBuffer, cbNew);
                if (RT_FAILURE(rc2))
                {
                    RTPollSetRemove(hPollSet, idPollSet);
                    rc2 = RTPipeClose(*phPipeR); AssertRC(rc2);
                    *phPipeR = NIL_RTPIPE;
                    return RT_SUCCESS(rc) ? rc2 : rc;
                }
                *pcbAllocated = cbNew;
            }

            /* Append the new data, terminating it. */
            memcpy(*ppszBuffer + *poffCur, szTmp, cbRead);
            *poffCur += cbRead;
            (*ppszBuffer)[*poffCur] = '\0';

            /* Check for null terminators in the string. */
            if (RT_SUCCESS(rc) && memchr(szTmp, '\0', cbRead))
                rc = VERR_NO_TRANSLATION;

            /* If we read a full buffer, try read some more. */
            if (RT_SUCCESS(rc) && cbRead == sizeof(szTmp))
                continue;
        }
        else if (rc2 != VINF_TRY_AGAIN)
        {
            if (RT_FAILURE(rc) && rc2 != VERR_BROKEN_PIPE)
                rc = rc2;
            RTPollSetRemove(hPollSet, idPollSet);
            rc2 = RTPipeClose(*phPipeR); AssertRC(rc2);
            *phPipeR = NIL_RTPIPE;
        }
        return rc;
    }
}
Пример #2
0
/**
 * Grows the command line string buffer.
 *
 * @returns VINF_SUCCESS or VERR_NO_STR_MEMORY.
 * @param   ppszCmdLine     Pointer to the command line string pointer.
 * @param   pcbCmdLineAlloc Pointer to the allocation length variable.
 * @param   cchMin          The minimum size to grow with, kind of.
 */
static int rtGetOptArgvToStringGrow(char **ppszCmdLine, size_t *pcbCmdLineAlloc, size_t cchMin)
{
    size_t cb = *pcbCmdLineAlloc;
    while (cb < cchMin)
        cb *= 2;
    cb *= 2;
    *pcbCmdLineAlloc = cb;
    return RTStrRealloc(ppszCmdLine, cb);
}
Пример #3
0
/**
 * 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);

}
Пример #4
0
static char *rtUriPercentDecodeN(const char *pszString, size_t cchString)
{
    AssertPtrReturn(pszString, NULL);
    AssertReturn(memchr(pszString, '\0', cchString) == NULL, NULL);

    /*
     * The new string can only get smaller, so use the input length as a
     * staring buffer size.
     */
    char *pszDecoded = RTStrAlloc(cchString + 1);
    if (pszDecoded)
    {
        /*
         * Knowing that the pszString itself is valid UTF-8, we only have to
         * validate the escape sequences.
         */
        size_t      cchLeft = cchString;
        char const *pchSrc  = pszString;
        char       *pchDst  = pszDecoded;
        while (cchLeft > 0)
        {
            const char *pchPct = (const char *)memchr(pchSrc, '%', cchLeft);
            if (pchPct)
            {
                size_t cchBefore = pchPct - pchSrc;
                if (cchBefore)
                {
                    memcpy(pchDst, pchSrc, cchBefore);
                    pchDst  += cchBefore;
                    pchSrc  += cchBefore;
                    cchLeft -= cchBefore;
                }

                char chHigh, chLow;
                if (   cchLeft >= 3
                    && RT_C_IS_XDIGIT(chHigh = pchSrc[1])
                    && RT_C_IS_XDIGIT(chLow  = pchSrc[2]))
                {
                    uint8_t b = RT_C_IS_DIGIT(chHigh) ? chHigh - '0' : (chHigh & ~0x20) - 'A' + 10;
                    b <<= 4;
                    b |= RT_C_IS_DIGIT(chLow) ? chLow - '0' : (chLow & ~0x20) - 'A' + 10;
                    *pchDst++ = (char)b;
                    pchSrc  += 3;
                    cchLeft -= 3;
                }
                else
                {
                    AssertFailed();
                    *pchDst++ = *pchSrc++;
                    cchLeft--;
                }
            }
            else
            {
                memcpy(pchDst, pchSrc, cchLeft);
                pchDst += cchLeft;
                pchSrc += cchLeft;
                cchLeft = 0;
                break;
            }
        }

        *pchDst = '\0';

        /*
         * If we've got lof space room in the result string, reallocate it.
         */
        size_t cchDecoded = pchDst - pszDecoded;
        Assert(cchDecoded <= cchString);
        if (cchString - cchDecoded > 64)
            RTStrRealloc(&pszDecoded, cchDecoded + 1);
    }
    return pszDecoded;
}