Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[release/6.0-rc1] Give tvOS a special value for Personal/MyDocuments #58056

Merged
merged 1 commit into from
Aug 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Runtime.InteropServices;

internal static partial class Interop
{
internal static partial class Sys
{
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SearchPath_TempDirectory")]
internal static extern string SearchPathTempDirectory();
}
}
1 change: 1 addition & 0 deletions src/libraries/Native/Unix/System.Native/entrypoints.c
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ static const Entry s_sysNative[] =
DllImportEntry(SystemNative_GetOSArchitecture)
DllImportEntry(SystemNative_GetProcessArchitecture)
DllImportEntry(SystemNative_SearchPath)
DllImportEntry(SystemNative_SearchPath_TempDirectory)
DllImportEntry(SystemNative_RegisterForSigChld)
DllImportEntry(SystemNative_SetDelayedSigChildConsoleConfigurationHandler)
DllImportEntry(SystemNative_SetTerminalInvalidationHandler)
Expand Down
6 changes: 6 additions & 0 deletions src/libraries/Native/Unix/System.Native/pal_searchpath.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,9 @@ const char* SystemNative_SearchPath(int32_t folderId)
__builtin_unreachable();
return NULL;
}

const char* SystemNative_SearchPath_TempDirectory()
{
__builtin_unreachable();
return NULL;
}
2 changes: 2 additions & 0 deletions src/libraries/Native/Unix/System.Native/pal_searchpath.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@
#include "pal_types.h"

PALEXPORT const char* SystemNative_SearchPath(int32_t folderId);

PALEXPORT const char* SystemNative_SearchPath_TempDirectory(void);
7 changes: 7 additions & 0 deletions src/libraries/Native/Unix/System.Native/pal_searchpath.m
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,10 @@
const char* path = [[url path] UTF8String];
return path == NULL ? NULL : strdup (path);
}

const char* SystemNative_SearchPath_TempDirectory()
{
NSString* tempPath = NSTemporaryDirectory();
const char *path = [tempPath UTF8String];
return path == NULL ? NULL : strdup (path);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2112,6 +2112,8 @@
<Compile Include="$(MSBuildThisFileDirectory)System\IO\FileSystem.Exists.Unix.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IO\FileSystemInfo.Unix.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IO\Path.Unix.cs" />
<Compile Condition="'$(IsiOSLike)' == 'true'" Include="$(MSBuildThisFileDirectory)System\IO\Path.Unix.iOS.cs" />
<Compile Condition="'$(IsiOSLike)' != 'true'" Include="$(MSBuildThisFileDirectory)System\IO\Path.Unix.NoniOS.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IO\PathInternal.Unix.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IO\PersistedFiles.Names.Unix.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\IO\RandomAccess.Unix.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace System.IO
{
public static partial class Path
{
private static string DefaultTempPath => "/tmp/";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ private static string RemoveLongPathPrefix(string path)
public static string GetTempPath()
{
const string TempEnvVar = "TMPDIR";
const string DefaultTempPath = "/tmp/";

// Get the temp path from the TMPDIR environment variable.
// If it's not set, just return the default path.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;

namespace System.IO
{
public static partial class Path
{
private static string? s_defaultTempPath;

private static string DefaultTempPath =>
s_defaultTempPath ?? (s_defaultTempPath = Interop.Sys.SearchPathTempDirectory()) ??
throw new InvalidOperationException();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,13 @@ public void FailFast_ExceptionStackTrace_InnerException()
}
}

[Fact]
[PlatformSpecific(TestPlatforms.AnyUnix | TestPlatforms.Browser)]
public void GetFolderPath_Unix_PersonalExists()
{
Assert.True(Directory.Exists(Environment.GetFolderPath(Environment.SpecialFolder.Personal)));
}

[Fact]
[PlatformSpecific(TestPlatforms.AnyUnix | TestPlatforms.Browser)] // Tests OS-specific environment
public void GetFolderPath_Unix_PersonalIsHomeAndUserProfile()
Expand All @@ -339,7 +346,11 @@ public void GetFolderPath_Unix_PersonalIsHomeAndUserProfile()
Assert.Equal(Environment.GetEnvironmentVariable("HOME"), Environment.GetFolderPath(Environment.SpecialFolder.Personal));
Assert.Equal(Environment.GetEnvironmentVariable("HOME"), Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));
}
Assert.Equal(Environment.GetEnvironmentVariable("HOME"), Environment.GetFolderPath(Environment.SpecialFolder.UserProfile));
// tvOS effectively doesn't have a HOME
if (!PlatformDetection.IstvOS)
{
Assert.Equal(Environment.GetEnvironmentVariable("HOME"), Environment.GetFolderPath(Environment.SpecialFolder.UserProfile));
}
}

[Theory]
Expand Down
2 changes: 1 addition & 1 deletion src/libraries/sendtohelixhelp.proj
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@
<TestTarget>$(AppleTestTarget)</TestTarget>
</XHarnessAppBundleToTest>
<!-- Create work items for run-only apps -->
<XHarnessAppBundleToTest Condition="Exists('$(TestArchiveRoot)runonly')" Include="$([System.IO.Directory]::GetDirectories('$(TestArchiveRoot)runonly', '*.app', System.IO.SearchOption.AllDirectories))" >
<XHarnessAppBundleToTest Condition="Exists('$(TestArchiveRoot)runonly') and '$(TargetOS)' != 'tvOS'" Include="$([System.IO.Directory]::GetDirectories('$(TestArchiveRoot)runonly', '*.app', System.IO.SearchOption.AllDirectories))" >
<!-- The sample app doesn't need test runner -->
<IncludesTestRunner>false</IncludesTestRunner>
<!-- The sample's C# Main method returns 42 so it should be considered by xharness as a success -->
Expand Down
3 changes: 3 additions & 0 deletions src/mono/System.Private.CoreLib/System.Private.CoreLib.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,9 @@
<Compile Include="$(CommonPath)Interop\OSX\System.Native\Interop.SearchPath.cs">
<Link>Common\Interop\OSX\Interop.SearchPath.cs</Link>
</Compile>
<Compile Include="$(CommonPath)Interop\OSX\System.Native\Interop.SearchPath.iOS.cs">
<Link>Common\Interop\OSX\Interop.SearchPath.iOS.cs</Link>
</Compile>
</ItemGroup>
<ItemGroup Condition="'$(TargetsBrowser)' == 'true'">
<Compile Include="$(BclSourcesRoot)\System\Threading\TimerQueue.Browser.Mono.cs" />
Expand Down
29 changes: 21 additions & 8 deletions src/mono/System.Private.CoreLib/src/System/Environment.iOS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,14 @@ private static string GetFolderPathCore(SpecialFolder folder, SpecialFolderOptio
{
switch (folder)
{
// TODO: fix for tvOS (https://github.com/dotnet/runtime/issues/34007)
// The "normal" NSDocumentDirectory is a read-only directory on tvOS
// and that breaks a lot of assumptions in the runtime and the BCL

case SpecialFolder.Personal:
case SpecialFolder.LocalApplicationData:
return Interop.Sys.SearchPath(NSSearchPathDirectory.NSDocumentDirectory);
return CombineDocumentDirectory(string.Empty);

case SpecialFolder.ApplicationData:
// note: at first glance that looked like a good place to return NSLibraryDirectory
// but it would break isolated storage for existing applications
return CombineSearchPath(NSSearchPathDirectory.NSDocumentDirectory, ".config");
return CombineDocumentDirectory(".config");

case SpecialFolder.Resources:
return Interop.Sys.SearchPath(NSSearchPathDirectory.NSLibraryDirectory); // older (8.2 and previous) would return String.Empty
Expand All @@ -63,7 +59,7 @@ private static string GetFolderPathCore(SpecialFolder folder, SpecialFolderOptio
return Path.Combine(GetFolderPathCore(SpecialFolder.Personal, SpecialFolderOption.None), "Pictures");

case SpecialFolder.Templates:
return CombineSearchPath(NSSearchPathDirectory.NSDocumentDirectory, "Templates");
return CombineDocumentDirectory("Templates");

case SpecialFolder.MyVideos:
return Path.Combine(GetFolderPathCore(SpecialFolder.Personal, SpecialFolderOption.None), "Videos");
Expand All @@ -72,7 +68,7 @@ private static string GetFolderPathCore(SpecialFolder folder, SpecialFolderOptio
return "/usr/share/templates";

case SpecialFolder.Fonts:
return CombineSearchPath(NSSearchPathDirectory.NSDocumentDirectory, ".fonts");
return CombineDocumentDirectory(".fonts");

case SpecialFolder.Favorites:
return CombineSearchPath(NSSearchPathDirectory.NSLibraryDirectory, "Favorites");
Expand Down Expand Up @@ -100,6 +96,23 @@ static string CombineSearchPath(NSSearchPathDirectory searchPath, string subdire
Path.Combine(path, subdirectory) :
string.Empty;
}

static string CombineDocumentDirectory(string subdirectory)
{
#if TARGET_TVOS
string? path = CombineSearchPath(NSSearchPathDirectory.NSLibraryDirectory, Path.Combine("Caches", "Documents", subdirectory));
// Special version of CombineSearchPath which creates the path if needed.
// This isn't needed for "real" search paths which always exist, but on tvOS
// the base path is really a subdirectory we define rather than an OS directory.
// In order to not treat Directory.Exists(SpecialFolder.ApplicationData) differently
// on tvOS, guarantee that it exists by creating it here
if (!Directory.Exists (path))
Directory.CreateDirectory (path);
#else
string? path = CombineSearchPath(NSSearchPathDirectory.NSDocumentDirectory, subdirectory);
#endif
return path;
}
}
}
}