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; }
/** * 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; }