AsReadOnlySpan -> AsSpan rename to fix build breaks
[platform/upstream/coreclr.git] / src / mscorlib / shared / System / IO / Path.Unix.cs
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4
5 using System.Diagnostics;
6 using System.Runtime.InteropServices;
7 using System.Text;
8
9 namespace System.IO
10 {
11     public static partial class Path
12     {
13         public static char[] GetInvalidFileNameChars() => new char[] { '\0', '/' };
14
15         public static char[] GetInvalidPathChars() => new char[] { '\0' };
16
17         // Expands the given path to a fully qualified path. 
18         public static string GetFullPath(string path)
19         {
20             if (path == null)
21                 throw new ArgumentNullException(nameof(path));
22
23             if (path.Length == 0)
24                 throw new ArgumentException(SR.Arg_PathEmpty, nameof(path));
25
26             if (path.IndexOf('\0') != -1)
27                 throw new ArgumentException(SR.Argument_InvalidPathChars, nameof(path)); 
28             
29             // Expand with current directory if necessary
30             if (!IsPathRooted(path))
31             {
32                 path = Combine(Interop.Sys.GetCwd(), path);
33             }
34
35             // We would ideally use realpath to do this, but it resolves symlinks, requires that the file actually exist,
36             // and turns it into a full path, which we only want if fullCheck is true.
37             string collapsedString = RemoveRelativeSegments(path);
38
39             Debug.Assert(collapsedString.Length < path.Length || collapsedString.ToString() == path,
40                 "Either we've removed characters, or the string should be unmodified from the input path.");
41
42             string result = collapsedString.Length == 0 ? PathInternal.DirectorySeparatorCharAsString : collapsedString;
43
44             return result;
45         }
46
47         public static string GetFullPath(string path, string basePath)
48         {
49             if (path == null)
50                 throw new ArgumentNullException(nameof(path));
51
52             if (basePath == null)
53                 throw new ArgumentNullException(nameof(basePath));
54
55             if (!IsPathFullyQualified(basePath))
56                 throw new ArgumentException(SR.Arg_BasePathNotFullyQualified, nameof(basePath));
57
58             if (basePath.Contains('\0') || path.Contains('\0'))
59                 throw new ArgumentException(SR.Argument_InvalidPathChars);
60
61             if (IsPathFullyQualified(path))
62                 return GetFullPath(path);
63
64             return GetFullPath(CombineNoChecks(basePath, path));
65         }
66
67         private static string RemoveLongPathPrefix(string path)
68         {
69             return path; // nop.  There's nothing special about "long" paths on Unix.
70         }
71
72         public static string GetTempPath()
73         {
74             const string TempEnvVar = "TMPDIR";
75             const string DefaultTempPath = "/tmp/";
76
77             // Get the temp path from the TMPDIR environment variable.
78             // If it's not set, just return the default path.
79             // If it is, return it, ensuring it ends with a slash.
80             string path = Environment.GetEnvironmentVariable(TempEnvVar);
81             return
82                 string.IsNullOrEmpty(path) ? DefaultTempPath :
83                 PathInternal.IsDirectorySeparator(path[path.Length - 1]) ? path :
84                 path + PathInternal.DirectorySeparatorChar;
85         }
86
87         public static string GetTempFileName()
88         {
89             const string Suffix = ".tmp";
90             const int SuffixByteLength = 4;
91
92             // mkstemps takes a char* and overwrites the XXXXXX with six characters
93             // that'll result in a unique file name.
94             string template = GetTempPath() + "tmpXXXXXX" + Suffix + "\0";
95             byte[] name = Encoding.UTF8.GetBytes(template);
96
97             // Create, open, and close the temp file.
98             IntPtr fd = Interop.CheckIo(Interop.Sys.MksTemps(name, SuffixByteLength));
99             Interop.Sys.Close(fd); // ignore any errors from close; nothing to do if cleanup isn't possible
100
101             // 'name' is now the name of the file
102             Debug.Assert(name[name.Length - 1] == '\0');
103             return Encoding.UTF8.GetString(name, 0, name.Length - 1); // trim off the trailing '\0'
104         }
105
106         public static bool IsPathRooted(string path)
107         {
108             if (path == null)
109                 return false;
110
111             return IsPathRooted(path.AsSpan());
112         }
113
114         public static bool IsPathRooted(ReadOnlySpan<char> path)
115         {
116             return path.Length > 0 && path[0] == PathInternal.DirectorySeparatorChar;
117         }
118
119         /// <summary>
120         /// Returns the path root or null if path is empty or null.
121         /// </summary>
122         public static string GetPathRoot(string path)
123         {
124             if (PathInternal.IsEffectivelyEmpty(path)) return null;
125
126             return IsPathRooted(path) ? PathInternal.DirectorySeparatorCharAsString : string.Empty;
127         }
128
129         public static ReadOnlySpan<char> GetPathRoot(ReadOnlySpan<char> path)
130         {
131             return PathInternal.IsEffectivelyEmpty(path) && IsPathRooted(path) ? PathInternal.DirectorySeparatorCharAsString.AsSpan() : ReadOnlySpan<char>.Empty;
132         }
133
134         /// <summary>Gets whether the system is case-sensitive.</summary>
135         internal static bool IsCaseSensitive
136         {
137             get
138             {
139                 #if PLATFORM_OSX
140                     return false;
141                 #else
142                     return true;
143                 #endif
144             }
145         }
146     }
147 }