| File: ContentStore.cs | Web Access |
| Project: src\sdk\src\Containers\Microsoft.NET.Build.Containers\Microsoft.NET.Build.Containers.csproj (Microsoft.NET.Build.Containers) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.NET.Build.Containers.Resources; namespace Microsoft.NET.Build.Containers; internal static class ContentStore { public static string ArtifactRoot { get; set; } = EnsureCacheDirectory(); public static string ContentRoot { get { string contentPath = Path.Join(ArtifactRoot, "Content"); CreateCacheDirectory(contentPath); return contentPath; } } public static string TempPath { get; } = Directory.CreateTempSubdirectory().FullName; public static string PathForDescriptor(Descriptor descriptor) { string digestString = descriptor.Digest; string digestValue = DigestUtils.GetEncoded(digestString); string extension = descriptor.MediaType switch { "application/vnd.docker.image.rootfs.diff.tar.gzip" or "application/vnd.oci.image.layer.v1.tar+gzip" or "application/vnd.docker.image.rootfs.foreign.diff.tar.gzip" => ".tar.gz", "application/vnd.docker.image.rootfs.diff.tar" or "application/vnd.oci.image.layer.v1.tar" => ".tar", _ => throw new ArgumentException(Resource.FormatString(nameof(Strings.UnrecognizedMediaType), descriptor.MediaType)) }; string descriptorPath = Path.Combine(ContentRoot, digestValue) + extension; return descriptorPath; } public static string GetTempFile() => Path.Join(TempPath, Path.GetRandomFileName()); /// <summary> /// Gets the path to the user cache directory for SDK container builds, creating it if it does /// not already exist. /// </summary> private static string EnsureCacheDirectory() { string userCacheDir = GetUserCacheDirectoryPath(); CreateCacheDirectory(userCacheDir); string dotnetCacheDir = Path.Join(userCacheDir, "dotnet"); CreateCacheDirectory(dotnetCacheDir); string containersCacheDir = Path.Join(dotnetCacheDir, "Containers"); CreateCacheDirectory(containersCacheDir); return containersCacheDir; } /// <summary> /// Creates a cache directory with user-scoped permissions based on the OS. /// </summary> /// <remarks> /// Permissions are only set for the leaf directory. The caller is expected to handle /// permissions for intermediate directories. /// </remarks> private static void CreateCacheDirectory(string path) { if (OperatingSystem.IsWindows()) { Directory.CreateDirectory(path); } else { // Per XDG_CACHE_HOME spec: if the cache directory doesn't exist, try to create it with // permissions 0700. If it already exists, don't try to change the permissions. // See https://specifications.freedesktop.org/basedir/latest/#referencing Directory.CreateDirectory(path, UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute); } } /// <summary> /// Gets the user-scoped cache directory, accounting for OS differences. /// </summary> private static string GetUserCacheDirectoryPath() { if (OperatingSystem.IsLinux()) { // See "XDG Base Directory Specification": // https://specifications.freedesktop.org/basedir/latest/ string? xdgCacheHome = Environment.GetEnvironmentVariable("XDG_CACHE_HOME"); if (!string.IsNullOrEmpty(xdgCacheHome) && Path.IsPathFullyQualified(xdgCacheHome)) { return xdgCacheHome; } // From the spec, if XDG_CACHE_HOME is not set then fall back to ~/.cache string userHomeDirectory = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); return Path.Join(userHomeDirectory, ".cache"); } if (OperatingSystem.IsMacOS()) { // See "macOS Library Directory Details": // https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/MacOSXDirectories/MacOSXDirectories.html string userHomeDirectory = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); return Path.Join(userHomeDirectory, "Library", "Caches"); } // On other platforms, use the local application data folder. string localAppData = Environment.GetFolderPath( Environment.SpecialFolder.LocalApplicationData, Environment.SpecialFolderOption.DoNotVerify); return localAppData; } }