示例#1
0
/**
 * Seeks a number of bytes relative to the current stream position.
 *
 * @returns IPRT status code.
 * @retval  VERR_SEEK if the new stream position is the middle of an EOL marker.
 *          This is a temporary restriction.
 *
 * @param   pStream             The stream.  Must be in read mode.
 * @param   offRelative         The offset to seek to.  A negative offset
 *                              rewinds and positive one fast forwards the
 *                              stream.  Will quietly stop at the beginning and
 *                              end of the stream.
 */
int ScmStreamSeekRelative(PSCMSTREAM pStream, ssize_t offRelative)
{
    size_t offAbsolute;
    if (offRelative >= 0)
        offAbsolute = pStream->off + offRelative;
    else if ((size_t)-offRelative <= pStream->off)
        offAbsolute = pStream->off + offRelative;
    else
        offAbsolute = 0;
    return ScmStreamSeekAbsolute(pStream, offAbsolute);
}
示例#2
0
/**
 * Reads @a cbToRead bytes into @a pvBuf.
 *
 * Will fail if end of stream is encountered before the entire read has been
 * completed.
 *
 * @returns IPRT status code.
 * @retval  VERR_EOF if there isn't @a cbToRead bytes left to read.  Stream
 *          position will be unchanged.
 *
 * @param   pStream             The stream.  Must be in read mode.
 * @param   pvBuf               The buffer to read into.
 * @param   cbToRead            The number of bytes to read.
 */
int ScmStreamRead(PSCMSTREAM pStream, void *pvBuf, size_t cbToRead)
{
    AssertReturn(!pStream->fWriteOrRead, VERR_PERMISSION_DENIED);
    if (RT_FAILURE(pStream->rc))
        return pStream->rc;

    /* If there isn't enough stream left, fail already. */
    if (RT_UNLIKELY(pStream->cb - pStream->off < cbToRead))
        return VERR_EOF;

    /* Copy the data and simply seek to the new stream position. */
    memcpy(pvBuf, &pStream->pch[pStream->off], cbToRead);
    return ScmStreamSeekAbsolute(pStream, pStream->off + cbToRead);
}
示例#3
0
/**
 * Queries the value of an SVN property.
 *
 * This will automatically adjust for scheduled changes.
 *
 * @returns IPRT status code.
 * @retval  VERR_INVALID_STATE if not a SVN WC file.
 * @retval  VERR_NOT_FOUND if the property wasn't found.
 * @param   pState              The rewrite state to work on.
 * @param   pszName             The property name.
 * @param   ppszValue           Where to return the property value.  Free this
 *                              using RTStrFree.  Optional.
 */
int ScmSvnQueryProperty(PSCMRWSTATE pState, const char *pszName, char **ppszValue)
{
    /*
     * Look it up in the scheduled changes.
     */
    size_t i = pState->cSvnPropChanges;
    while (i-- > 0)
        if (!strcmp(pState->paSvnPropChanges[i].pszName, pszName))
        {
            const char *pszValue = pState->paSvnPropChanges[i].pszValue;
            if (!pszValue)
                return VERR_NOT_FOUND;
            if (ppszValue)
                return RTStrDupEx(ppszValue, pszValue);
            return VINF_SUCCESS;
        }

#ifdef SCM_WITHOUT_LIBSVN
    int rc;
    scmSvnFindSvnBinary(pState);
    if (g_enmSvnVersion < kScmSvnVersion_1_7)
    {
        /*
         * Hack: Read the .svn/props/<file>.svn-work file exists.
         */
        char szPath[RTPATH_MAX];
        rc = scmSvnConstructName(pState, ".svn/props/", ".svn-work", szPath);
        if (RT_SUCCESS(rc) && !RTFileExists(szPath))
            rc = scmSvnConstructName(pState, ".svn/prop-base/", ".svn-base", szPath);
        if (RT_SUCCESS(rc))
        {
            SCMSTREAM Stream;
            rc = ScmStreamInitForReading(&Stream, szPath);
            if (RT_SUCCESS(rc))
            {
                /*
                 * The current format is K len\n<name>\nV len\n<value>\n" ... END.
                 */
                rc = VERR_NOT_FOUND;
                size_t const    cchName = strlen(pszName);
                SCMEOL          enmEol;
                size_t          cchLine;
                const char     *pchLine;
                while ((pchLine = ScmStreamGetLine(&Stream, &cchLine, &enmEol)) != NULL)
                {
                    /*
                     * Parse the 'K num' / 'END' line.
                     */
                    if (   cchLine == 3
                        && !memcmp(pchLine, "END", 3))
                        break;
                    size_t cchKey;
                    if (   cchLine < 3
                        || pchLine[0] != 'K'
                        || pchLine[1] != ' '
                        || !scmSvnReadNumber(&pchLine[2], cchLine - 2, &cchKey)
                        || cchKey == 0
                        || cchKey > 4096)
                    {
                        RTMsgError("%s:%u: Unexpected data '%.*s'\n", szPath, ScmStreamTellLine(&Stream), cchLine, pchLine);
                        rc = VERR_PARSE_ERROR;
                        break;
                    }

                    /*
                     * Match the key and skip to the value line.  Don't bother with
                     * names containing EOL markers.
                     */
                    size_t const offKey = ScmStreamTell(&Stream);
                    bool fMatch = cchName == cchKey;
                    if (fMatch)
                    {
                        pchLine = ScmStreamGetLine(&Stream, &cchLine, &enmEol);
                        if (!pchLine)
                            break;
                        fMatch = cchLine == cchName
                              && !memcmp(pchLine, pszName, cchName);
                    }

                    if (RT_FAILURE(ScmStreamSeekAbsolute(&Stream, offKey + cchKey)))
                        break;
                    if (RT_FAILURE(ScmStreamSeekByLine(&Stream, ScmStreamTellLine(&Stream) + 1)))
                        break;

                    /*
                     * Read and Parse the 'V num' line.
                     */
                    pchLine = ScmStreamGetLine(&Stream, &cchLine, &enmEol);
                    if (!pchLine)
                        break;
                    size_t cchValue;
                    if (   cchLine < 3
                        || pchLine[0] != 'V'
                        || pchLine[1] != ' '
                        || !scmSvnReadNumber(&pchLine[2], cchLine - 2, &cchValue)
                        || cchValue > _1M)
                    {
                        RTMsgError("%s:%u: Unexpected data '%.*s'\n", szPath, ScmStreamTellLine(&Stream), cchLine, pchLine);
                        rc = VERR_PARSE_ERROR;
                        break;
                    }

                    /*
                     * If we have a match, allocate a return buffer and read the
                     * value into it.  Otherwise skip this value and continue
                     * searching.
                     */
                    if (fMatch)
                    {
                        if (!ppszValue)
                            rc = VINF_SUCCESS;
                        else
                        {
                            char *pszValue;
                            rc = RTStrAllocEx(&pszValue, cchValue + 1);
                            if (RT_SUCCESS(rc))
                            {
                                rc = ScmStreamRead(&Stream, pszValue, cchValue);
                                if (RT_SUCCESS(rc))
                                    *ppszValue = pszValue;
                                else
                                    RTStrFree(pszValue);
                            }
                        }
                        break;
                    }

                    if (RT_FAILURE(ScmStreamSeekRelative(&Stream, cchValue)))
                        break;
                    if (RT_FAILURE(ScmStreamSeekByLine(&Stream, ScmStreamTellLine(&Stream) + 1)))
                        break;
                }

                if (RT_FAILURE(ScmStreamGetStatus(&Stream)))
                {
                    rc = ScmStreamGetStatus(&Stream);
                    RTMsgError("%s: stream error %Rrc\n", szPath, rc);
                }
                ScmStreamDelete(&Stream);
            }
        }

        if (rc == VERR_FILE_NOT_FOUND)
            rc = VERR_NOT_FOUND;
    }
    else
    {
        const char *apszArgs[] = { g_szSvnPath, "propget", "--strict", pszName, pState->pszFilename, NULL };
        char       *pszValue;
        rc = scmSvnRunAndGetOutput(pState, apszArgs, false, &pszValue);
        if (RT_SUCCESS(rc))
        {
            if (pszValue && *pszValue)
            {
                if (ppszValue)
                {
                    *ppszValue = pszValue;
                    pszValue = NULL;
                }
            }
            else
                rc = VERR_NOT_FOUND;
            RTStrFree(pszValue);
        }
    }
    return rc;

#else
    NOREF(pState);
#endif
    return VERR_NOT_FOUND;
}