RTDECL(int) RTPathIsSame(const char *pszPath1, const char *pszPath2)
{
    /*
     * Simple checks based on the path values.
     */
    if (pszPath1 == pszPath2)
        return true;
    if (!pszPath1)
        return false;
    if (!pszPath2)
        return false;
    if (!strcmp(pszPath1, pszPath2))
        return true;

    /*
     * If the files exist, try use the attributes.
     */
    RTFSOBJINFO ObjInfo1, ObjInfo2;
    int rc = RTPathQueryInfoEx(pszPath1, &ObjInfo1, RTFSOBJATTRADD_UNIX, RTPATH_F_ON_LINK);
    if (RT_SUCCESS(rc))
        rc = RTPathQueryInfoEx(pszPath2, &ObjInfo2, RTFSOBJATTRADD_UNIX, RTPATH_F_ON_LINK);
    if (RT_SUCCESS(rc))
    {
        if ((ObjInfo1.Attr.fMode & RTFS_TYPE_MASK) != (ObjInfo2.Attr.fMode & RTFS_TYPE_MASK))
            return false;
        if (ObjInfo1.Attr.u.Unix.INodeIdDevice       != ObjInfo2.Attr.u.Unix.INodeIdDevice)
            return false;
        if (ObjInfo1.Attr.u.Unix.INodeId             != ObjInfo2.Attr.u.Unix.INodeId)
            return false;
        if (ObjInfo1.Attr.u.Unix.GenerationId        != ObjInfo2.Attr.u.Unix.GenerationId)
            return false;
        if (   ObjInfo1.Attr.u.Unix.INodeIdDevice != 0
            && ObjInfo1.Attr.u.Unix.INodeId       != 0)
            return true;
    }

    /*
     * Fallback, compare absolute/real paths. Return failure on paths that are
     * too long.
     */
    char szPath1[RTPATH_MAX];
    rc = RTPathAbs(pszPath1, szPath1, sizeof(szPath1));
    AssertRCReturn(rc, VERR_FILENAME_TOO_LONG);

    char szPath2[RTPATH_MAX];
    rc = RTPathAbs(pszPath2, szPath2, sizeof(szPath2)); AssertRC(rc);
    AssertRCReturn(rc, VERR_FILENAME_TOO_LONG);

    if (RTPathCompare(szPath1, szPath2) == 0)
        return true;

    /** @todo Relsolve any symbolic links in the paths. Too lazy for that right
     *        now. */
    return false;
}
Example #2
0
/**
 * Creates a UUID mapping for the file.
 *
 * @returns IPRT status code.
 * @param   pszCacheFile    The path to the file in the cache.
 * @param   pFileUuid       The UUID of the file.
 * @param   pszUuidMapDir   The UUID map subdirectory in the cache, if this is
 *                          wanted, otherwise NULL.
 * @param   pCfg            The configuration.
 */
static int rtDbgSymCacheAddCreateUuidMapping(const char *pszCacheFile, PRTUUID pFileUuid,
                                             const char *pszUuidMapDir, PCRTDBGSYMCACHEADDCFG pCfg)
{
    /*
     * Create the UUID map entry first, deep.
     */
    char szMapPath[RTPATH_MAX];
    int rc = RTPathJoin(szMapPath, sizeof(szMapPath) - sizeof("/xxxx/yyyy/xxxx/yyyy/xxxx/zzzzzzzzzzzz") + 1,
                        pCfg->pszCache, pszUuidMapDir);
    if (RT_FAILURE(rc))
        return RTMsgErrorRc(rc, "Error constructing UUID map path (RTPathJoin): %Rrc", rc);

    size_t cch = strlen(szMapPath);
    szMapPath[cch] = '-';

    rc = RTUuidToStr(pFileUuid, &szMapPath[cch + 2], sizeof(szMapPath) - cch);
    if (RT_FAILURE(rc))
        return RTMsgErrorRc(rc, "Error constructing UUID map path (RTUuidToStr): %Rrc", rc);

    /* Uppercase the whole lot. */
    RTStrToUpper(&szMapPath[cch + 2]);

    /* Split the first dword in two. */
    szMapPath[cch + 1] = szMapPath[cch + 2];
    szMapPath[cch + 2] = szMapPath[cch + 3];
    szMapPath[cch + 3] = szMapPath[cch + 4];
    szMapPath[cch + 4] = szMapPath[cch + 5];
    szMapPath[cch + 5] = '-';

    /*
     * Create the directories in the path.
     */
    char chSaved = RTPATH_SLASH;
    for (unsigned i = 0; i < 6; i++, cch += 5)
    {
        Assert(szMapPath[cch] == '-');
        szMapPath[cch] = '\0';
        if (!RTDirExists(szMapPath))
        {
            rc = RTDirCreate(szMapPath, 0755, RTDIRCREATE_FLAGS_NOT_CONTENT_INDEXED_NOT_CRITICAL);
            if (RT_FAILURE(rc))
                return RTMsgErrorRc(rc, "RTDirCreate failed on '%s' (UUID map path): %Rrc", szMapPath, rc);
        }
        szMapPath[cch] = RTPATH_SLASH;
    }
    cch -= 5;

    /*
     * Calculate a relative path from there to the actual file.
     */
    char szLinkTarget[RTPATH_MAX];
    //szMapPath[cch] = '\0';
    rc = RTPathCalcRelative(szLinkTarget, sizeof(szLinkTarget), szMapPath, pszCacheFile);
    //szMapPath[cch] = RTPATH_SLASH;
    if (RT_FAILURE(rc))
        return RTMsgErrorRc(rc, "Failed to calculate relative path from '%s' to '%s': %Rrc", szMapPath, pszCacheFile, rc);

    /*
     * If there is already a link there, check if it matches or whether
     * perhaps it's target doesn't exist.
     */
    RTFSOBJINFO ObjInfo;
    rc = RTPathQueryInfoEx(szMapPath, &ObjInfo, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
    if (RT_SUCCESS(rc))
    {
        if (RTFS_IS_SYMLINK(ObjInfo.Attr.fMode))
        {
            rc = RTPathQueryInfoEx(szMapPath, &ObjInfo, RTFSOBJATTRADD_NOTHING, RTPATH_F_FOLLOW_LINK);
            if (RT_SUCCESS(rc))
            {
                char *pszCurTarget = NULL;
                rc = RTSymlinkReadA(szMapPath, &pszCurTarget);
                if (RT_FAILURE(rc))
                    return RTMsgErrorRc(rc, "UUID map: failed to read existing symlink '%s': %Rrc", szMapPath, rc);
                if (RTPathCompare(pszCurTarget, szLinkTarget) == 0)
                    RTMsgInfo("UUID map: existing link '%s' has the same target ('%s').", szMapPath, pszCurTarget);
                else
                {
                    RTMsgError("UUID map: Existing mapping '%s' pointing to '%s' insted of '%s'",
                               szMapPath, pszCurTarget, szLinkTarget);
                    rc = VERR_ALREADY_EXISTS;
                }
                RTStrFree(pszCurTarget);
                return rc;
            }
            else
                RTMsgInfo("UUID map: replacing dangling link '%s'", szMapPath);
            RTSymlinkDelete(szMapPath, 0 /*fFlags*/);
        }
        else if (RTFS_IS_FILE(ObjInfo.Attr.fMode))
            return RTMsgErrorRc(VERR_IS_A_FILE,
                                "UUID map: found file at '%s', expect symbolic link or nothing.", szMapPath);
        else if (RTFS_IS_DIRECTORY(ObjInfo.Attr.fMode))
            return RTMsgErrorRc(VERR_IS_A_DIRECTORY,
                                "UUID map: found directory at '%s', expect symbolic link or nothing.", szMapPath);
        else
            return RTMsgErrorRc(VERR_NOT_SYMLINK,
                                "UUID map: Expected symbolic link or nothing at '%s', found: fMode=%#x",
                                szMapPath, ObjInfo.Attr.fMode);
    }

    /*
     * Create the symbolic link.
     */
    rc = RTSymlinkCreate(szMapPath, szLinkTarget, RTSYMLINKTYPE_FILE, 0);
    if (RT_FAILURE(rc))
        return RTMsgErrorRc(rc, "Failed to create UUID map symlink '%s' to '%s': %Rrc", szMapPath, szLinkTarget, rc);
    RTMsgInfo("UUID map: %s  =>  %s", szMapPath, szLinkTarget);
    return VINF_SUCCESS;
}
/**
 *  Shared initialization code. Called from the other constructors.
 *
 *  @note
 *      Must be called from under the object's lock!
 */
HRESULT SharedFolder::protectedInit(VirtualBoxBase *aParent,
                                    const Utf8Str &aName,
                                    const Utf8Str &aHostPath,
                                    bool aWritable,
                                    bool aAutoMount,
                                    bool fFailOnError)
{
    LogFlowThisFunc(("aName={%s}, aHostPath={%s}, aWritable={%d}, aAutoMount={%d}\n",
                      aName.c_str(), aHostPath.c_str(), aWritable, aAutoMount));

    ComAssertRet(aParent && aName.isNotEmpty() && aHostPath.isNotEmpty(), E_INVALIDARG);

    Utf8Str hostPath = aHostPath;
    size_t hostPathLen = hostPath.length();

    /* Remove the trailing slash unless it's a root directory
     * (otherwise the comparison with the RTPathAbs() result will fail at least
     * on Linux). Note that this isn't really necessary for the shared folder
     * itself, since adding a mapping eventually results into a
     * RTDirOpenFiltered() call (see HostServices/SharedFolders) that seems to
     * accept both the slashified paths and not. */
#if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS)
    if (hostPathLen > 2 &&
        RTPATH_IS_SEP (hostPath.c_str()[hostPathLen - 1]) &&
        RTPATH_IS_VOLSEP (hostPath.c_str()[hostPathLen - 2]))
        ;
#else
    if (hostPathLen == 1 && RTPATH_IS_SEP(hostPath[0]))
        ;
#endif
    else
        hostPath.stripTrailingSlash();

    if (fFailOnError)
    {
        /* Check whether the path is full (absolute) */
        char hostPathFull[RTPATH_MAX];
        int vrc = RTPathAbsEx(NULL,
                              hostPath.c_str(),
                              hostPathFull,
                              sizeof (hostPathFull));
        if (RT_FAILURE(vrc))
            return setError(E_INVALIDARG,
                            tr("Invalid shared folder path: '%s' (%Rrc)"),
                            hostPath.c_str(), vrc);

        if (RTPathCompare(hostPath.c_str(), hostPathFull) != 0)
            return setError(E_INVALIDARG,
                            tr("Shared folder path '%s' is not absolute"),
                            hostPath.c_str());
    }

    unconst(mParent) = aParent;

    unconst(m->strName) = aName;
    unconst(m->strHostPath) = hostPath;
    m->fWritable = aWritable;
    m->fAutoMount = aAutoMount;

    return S_OK;
}