934
935
private async _resolveFileSystemPaths(paths: string[] | undefined): Promise<string[]> {
936
>
const resolvedPaths = await Promise.all((paths ?? []).map(path => this._resolveFileSystemPath(path)));
terminalSandboxEngine.ts
937
>
const seenPaths = new Set<string>();
938
>
return resolvedPaths.flat().filter(path => {
939
>
const comparisonKey = this._getFileSystemPathComparisonKey(path);
940
>
if (seenPaths.has(comparisonKey)) {
941
return false;
942
}
944
>
return true;
945
>
});
946
>
}
947
948
private _getFileSystemPathComparisonKey(path: string): string {
949
>
return this._os === OperatingSystem.Windows ? path.replace(/\//g, '\\').toLowerCase() : path;
terminalSandboxEngine.ts
950
>
}
951
952
private async _resolveFileSystemPath(path: string): Promise<string[]> {
953
>
const expandedPath = this._os === OperatingSystem.Linux ? this._expandHomePath(path) : path;
terminalSandboxEngine.ts
954
>
if (!this._isAbsoluteFileSystemPath(expandedPath)) {
955
return [expandedPath];
956
}
958
>
try {
959
>
const realpath = await this._fileService.realpath(this._toFileSystemResource(expandedPath));
960
>
const resolvedPath = realpath ? this._getUriPath(realpath) : undefined;
961
>
// Keep the expanded path (the configured path after home expansion) so permissions apply when accessed through the symlink.
962
>
// Also include the resolved path (the canonical symlink target) so the same permissions apply when accessed directly.
963
>
return resolvedPath && resolvedPath !== expandedPath ? [expandedPath, resolvedPath] : [expandedPath];
964
>
} catch {
965
return [expandedPath];
966
}
968
969
private _isAbsoluteFileSystemPath(path: string): boolean {