/**
 * Adds a file or directory.
 *
 * @returns Program exit code.
 * @param   pszPath                 The user supplied path to the file or directory.
 * @param   pszCache                The path to the cache.
 * @param   fRecursive              Whether to process directories recursively.
 * @param   fOverwriteOnConflict    Whether to overwrite existing cache entry on
 *                                  conflict, or just leave it.
 */
static RTEXITCODE rtDbgSymCacheAddFileOrDir(const char *pszPath, const char *pszCache, bool fRecursive,
        bool fOverwriteOnConflict)
{
    RT_NOREF1(fOverwriteOnConflict);
    RTDBGSYMCACHEADDCFG Cfg;
    Cfg.fRecursive      = fRecursive;
    Cfg.pszCache        = pszCache;
    Cfg.pszFilter       = NULL;

    int rc;
    RTDBGSYMCACHEFILETYPE enmType = rtDbgSymCacheFigureType(pszPath);
    switch (enmType)
    {
    default:
    case RTDBGSYMCACHEFILETYPE_INVALID:
        return RTMsgErrorExit(RTEXITCODE_FAILURE, "Invalid: '%s'", pszPath);

    case RTDBGSYMCACHEFILETYPE_DIR_FILTER:
        Cfg.pszFilter = RTPathFilename(pszPath);
    /* fall thru */
    case RTDBGSYMCACHEFILETYPE_DIR:
        rc = rtDbgSymCacheAddDir(pszPath, &Cfg);
        break;

    case RTDBGSYMCACHEFILETYPE_DEBUG_FILE:
        rc = rtDbgSymCacheAddDebugFile(pszPath, &Cfg);
        break;

    case RTDBGSYMCACHEFILETYPE_IMAGE_FILE:
        rc = rtDbgSymCacheAddImageFile(pszPath, NULL /*pszExtraSuff*/, RTDBG_CACHE_UUID_MAP_DIR_IMAGES, &Cfg);
        break;

    case RTDBGSYMCACHEFILETYPE_DEBUG_BUNDLE:
    case RTDBGSYMCACHEFILETYPE_IMAGE_BUNDLE:
    {
        size_t cchPath     = strlen(pszPath);
        size_t cchFilename = strlen(RTPathFilename(pszPath));
        char szPathBuf[RTPATH_MAX];
        if (cchPath < sizeof(szPathBuf))
        {
            memcpy(szPathBuf, pszPath, cchPath + 1);
            if (enmType == RTDBGSYMCACHEFILETYPE_DEBUG_BUNDLE)
                rc = rtDbgSymCacheAddDebugBundle(szPathBuf, cchPath - cchFilename, cchFilename, &Cfg);
            else
            {
                RTDIRENTRYEX DirEntry;
                rc = rtDbgSymCacheAddImageBundle(szPathBuf, cchPath - cchFilename, cchFilename, &DirEntry, &Cfg);
            }
        }
        else
            rc = RTMsgErrorRc(VERR_FILENAME_TOO_LONG, "Filename too long: '%s'", pszPath);
        break;
    }

    case RTDBGSYMCACHEFILETYPE_IGNORE:
        rc = RTMsgErrorRc(VERR_INVALID_PARAMETER, "Invalid file: '%s'", pszPath);
        break;
    }
    return RT_SUCCESS(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
}
Beispiel #2
0
/**
 * Recursive worker for rtDbgSymCacheAddDir, for minimal stack wasting.
 *
 * @returns IPRT status code (fully bitched).
 * @param   pszPath             Pointer to a RTPATH_MAX size buffer containing
 *                              the path to the current directory ending with a
 *                              slash.
 * @param   cchPath             The size of the current directory path.
 * @param   pDirEntry           Pointer to the RTDIRENTRYEX structure to use.
 * @param   pCfg                The configuration.
 */
static int rtDbgSymCacheAddDirWorker(char *pszPath, size_t cchPath, PRTDIRENTRYEX pDirEntry, PCRTDBGSYMCACHEADDCFG pCfg)
{
    /*
     * Open the directory.
     */
    PRTDIR pDir;
    int rc, rc2;
    if (pCfg->pszFilter)
    {
        rc = RTStrCopy(&pszPath[cchPath], RTPATH_MAX - cchPath, pCfg->pszFilter);
        if (RT_FAILURE(rc))
        {
            pszPath[cchPath] = '\0';
            return RTMsgErrorRc(rc, "Filename too long (%Rrc): '%s" RTPATH_SLASH_STR "%s'", rc, pszPath, pCfg->pszFilter);
        }
        rc = RTDirOpenFiltered(&pDir, pszPath, RTDIRFILTER_WINNT, 0 /*fFlags*/);
    }
    else
        rc = RTDirOpen(&pDir, pszPath);
    if (RT_FAILURE(rc))
        return RTMsgErrorRc(rc, "RTDirOpen%s failed on '%s': %Rrc", pCfg->pszFilter ? "Filtered" : "", pszPath, rc);

    /*
     * Enumerate the files.
     */
    for (;;)
    {
        rc2 = RTDirReadEx(pDir, pDirEntry, NULL, RTFSOBJATTRADD_NOTHING, RTPATH_F_FOLLOW_LINK);
        if (RT_FAILURE(rc2))
        {
            pszPath[cchPath] = '\0';
            if (rc2 != VERR_NO_MORE_FILES)
            {
                RTMsgError("RTDirReadEx failed in '%s': %Rrc\n", pszPath, rc2);
                rc = rc2;
            }
            break;
        }

        /* Skip dot and dot-dot. */
        if (RTDirEntryExIsStdDotLink(pDirEntry))
            continue;

        /* Construct a full path. */
        rc = RTStrCopy(&pszPath[cchPath], RTPATH_MAX, pDirEntry->szName);
        if (RT_FAILURE(rc))
        {
            pszPath[cchPath] = '\0';
            RTMsgError("File name too long in '%s': '%s' (%Rrc)", pszPath, pDirEntry->szName, rc);
            break;
        }

        switch (rtDbgSymCacheFigureType2(pszPath, &pDirEntry->Info))
        {
            case RTDBGSYMCACHEFILETYPE_DIR:
                if (!pCfg->fRecursive)
                    RTMsgInfo("Skipping directory '%s'...", pszPath);
                else
                {
                    if (cchPath + pDirEntry->cbName + 3 <= RTPATH_MAX)
                    {
                        pszPath[cchPath + pDirEntry->cbName] = RTPATH_SLASH;
                        pszPath[cchPath + pDirEntry->cbName + 1] = '\0';
                        rc2 = rtDbgSymCacheAddDirWorker(pszPath, cchPath + pDirEntry->cbName + 1, pDirEntry, pCfg);
                    }
                    else
                    {
                        RTMsgError("File name too long in '%s': '%s' (%Rrc)", pszPath, pDirEntry->szName, rc);
                        rc2 = VERR_FILENAME_TOO_LONG;
                    }
                }
                break;

            case RTDBGSYMCACHEFILETYPE_DEBUG_FILE:
                rc2 = rtDbgSymCacheAddDebugFile(pszPath, pCfg);
                break;

            case RTDBGSYMCACHEFILETYPE_IMAGE_FILE:
                rc2 = rtDbgSymCacheAddImageFile(pszPath, NULL /*pszExtraSuff*/, RTDBG_CACHE_UUID_MAP_DIR_IMAGES, pCfg);
                break;

            case RTDBGSYMCACHEFILETYPE_DEBUG_BUNDLE:
                rc2 = rtDbgSymCacheAddDebugBundle(pszPath, cchPath, pDirEntry->cbName, pCfg);
                break;

            case RTDBGSYMCACHEFILETYPE_IMAGE_BUNDLE:
                rc2 = rtDbgSymCacheAddImageBundle(pszPath, cchPath, pDirEntry->cbName, pDirEntry, pCfg);
                break;

            case RTDBGSYMCACHEFILETYPE_DIR_FILTER:
            case RTDBGSYMCACHEFILETYPE_INVALID:
                rc2 = RTMsgErrorRc(VERR_INTERNAL_ERROR_2, "Invalid: '%s'", pszPath);
                break;

            case RTDBGSYMCACHEFILETYPE_IGNORE:
                rc2 = VINF_SUCCESS;
                break;
        }

        if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
            rc = rc2;
    }

    /*
     * Clean up.
     */
    rc2 = RTDirClose(pDir);
    if (RT_FAILURE(rc2))
    {
        RTMsgError("RTDirClose failed in '%s': %Rrc", pszPath, rc);
        rc = rc2;
    }
    return rc;
}